firmware/br-ext-chip-fullhan/board/fh8852v200/kernel/patches/00_fh8852_kernel-4.9.129.patch

155176 lines
3.9 MiB
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

diff --git a/Documentation/devicetree/bindings/arm/fh.txt b/Documentation/devicetree/bindings/arm/fh.txt
new file mode 100644
index 00000000..e69de29b
diff --git a/Documentation/devicetree/bindings/fh,fh_rtc.txt b/Documentation/devicetree/bindings/fh,fh_rtc.txt
new file mode 100644
index 00000000..65d26208
--- /dev/null
+++ b/Documentation/devicetree/bindings/fh,fh_rtc.txt
@@ -0,0 +1,6 @@
+Example:
+ rtc: rtc@f1500000 {
+ compatible = "fh,fh_rtc";
+ reg = <0xf1500000 0xc00>;
+
+ };
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index bceffffb..388647a0 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -100,6 +100,7 @@ everspin Everspin Technologies, Inc.
excito Excito
ezchip EZchip Semiconductor
fcs Fairchild Semiconductor
+fh Fullhan Microelectronic Co.,Ltd
firefly Firefly
focaltech FocalTech Systems Co.,Ltd
friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd
diff --git a/Makefile b/Makefile
index 3f3c3403..95dc9f0a 100644
--- a/Makefile
+++ b/Makefile
@@ -638,10 +638,19 @@ KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context)
KBUILD_CFLAGS += $(call cc-disable-warning, attribute-alias)
+ifneq ($(findstring -DCONFIG_EMULATION, $(EXTRA_CFLAGS)),)
+$(info ### EMULATION ENVIRONMENT, use EXTRA_CFLAGS: $(EXTRA_CFLAGS))
+export CONFIG_EMULATION := y
+export CONFIG_KERNEL_NO_COMPRESS := y
+endif
+
ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
+# only enable these options when build kernel
+ifeq ($(KBUILD_EXTMOD),)
KBUILD_CFLAGS += $(call cc-option,-ffunction-sections,)
KBUILD_CFLAGS += $(call cc-option,-fdata-sections,)
endif
+endif
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os $(call cc-disable-warning,maybe-uninitialized,)
@@ -1600,7 +1609,7 @@ export_report:
endif #ifeq ($(config-targets),1)
endif #ifeq ($(mixed-targets),1)
-PHONY += checkstack kernelrelease kernelversion image_name
+PHONY += checkstack kernelrelease kernelversion image_name fhdtbimage
# UML needs a little special treatment here. It wants to use the host
# toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone
@@ -1611,6 +1620,14 @@ CHECKSTACK_ARCH := $(SUBARCH)
else
CHECKSTACK_ARCH := $(ARCH)
endif
+
+PROJECT_NAME=$(shell grep -e '^CONFIG_MACH_FH.*' .config|sed 's/CONFIG_MACH_\(.*\)=y/\1/'|awk '{print tolower($$0)}')
+
+fhdtbimage: dtbs uImage
+ echo $(PROJECT_NAME)
+ cat arch/arm/boot/uImage arch/arm/boot/dts/${PROJECT_NAME}.dtb > arch/arm/boot/uImage_${PROJECT_NAME}
+
+
checkstack:
$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
$(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH)
diff --git a/arch/Kconfig b/arch/Kconfig
index b39d0f93..e675fadd 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -477,21 +477,6 @@ config THIN_ARCHIVES
Select this if the architecture wants to use thin archives
instead of ld -r to create the built-in.o files.
-config LD_DEAD_CODE_DATA_ELIMINATION
- bool
- help
- Select this if the architecture wants to do dead code and
- data elimination with the linker by compiling with
- -ffunction-sections -fdata-sections and linking with
- --gc-sections.
-
- This requires that the arch annotates or otherwise protects
- its external entry points from being discarded. Linker scripts
- must also merge .text.*, .data.*, and .bss.* correctly into
- output sections. Care must be taken not to pull in unrelated
- sections (e.g., '.text.init'). Typically '.' in section names
- is used to distinguish them from label names / C identifiers.
-
config HAVE_ARCH_WITHIN_STACK_FRAMES
bool
help
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b5d529fd..402f22c3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -68,6 +68,7 @@ config ARM
select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_MEMBLOCK
+ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if !FUNCTION_TRACER
select HAVE_MOD_ARCH_SPECIFIC
select HAVE_NMI
select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
@@ -402,6 +403,17 @@ config ARCH_FOOTBRIDGE
help
Support for systems based on the DC21285 companion chip
("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
+
+config ARCH_FULLHAN
+ select SPARSE_IRQ
+ select MULTI_IRQ_HANDLER
+ select COMMON_CLK
+ select GENERIC_CLOCKEVENTS
+ select CLKSRC_OF if OF
+ select ARM_PATCH_PHYS_VIRT
+ bool "Fullhan SoC Support"
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARCH_REQUIRE_GPIOLIB
config ARCH_NETX
bool "Hilscher NetX based"
@@ -740,6 +752,7 @@ source "arch/arm/mach-dove/Kconfig"
source "arch/arm/mach-ep93xx/Kconfig"
source "arch/arm/mach-footbridge/Kconfig"
+source "arch/arm/mach-fh/Kconfig"
source "arch/arm/mach-gemini/Kconfig"
@@ -947,7 +960,7 @@ endif
config PJ4B_ERRATA_4742
bool "PJ4B Errata 4742: IDLE Wake Up Commands can Cause the CPU Core to Cease Operation"
- depends on CPU_PJ4B && MACH_ARMADA_370
+ depends on CPU_PJ4B && MACH_ARMADA_370 || ARCH_FULLHAN
default y
help
When coming out of either a Wait for Interrupt (WFI) or a Wait for
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index d83f7c36..736e9fff 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -270,6 +270,12 @@ choice
help
Say Y here if you want the debug print routines to direct
their output to the 8250 at PCI COM1.
+ config DEBUG_FH_UART
+ bool "Fullhan Debug UART"
+ depends on ARCH_FULLHAN
+ help
+ Say Y here if you want kernel low-level debugging support
+ on FULLHAN UART.
config DEBUG_GEMINI
bool "Kernel low-level debugging messages via Cortina Systems Gemini UART"
@@ -1432,6 +1438,8 @@ config DEBUG_LL_INCLUDE
default "debug/bcm63xx.S" if DEBUG_BCM63XX_UART
default "debug/digicolor.S" if DEBUG_DIGICOLOR_UA0
default "debug/brcmstb.S" if DEBUG_BRCMSTB_UART
+ default "debug/fh.S" if DEBUG_FH_UART
+
default "mach/debug-macro.S"
# Compatibility options for PL01x
@@ -1528,6 +1536,7 @@ config DEBUG_UART_PHYS
default 0xf8020000 if DEBUG_AT91_SAMA5D2_UART1
default 0xf8b00000 if DEBUG_HIX5HD2_UART
default 0xf991e000 if DEBUG_QCOM_UARTDM
+ default 0xf0700000 if DEBUG_FH_UART
default 0xfc00c000 if DEBUG_AT91_SAMA5D4_USART3
default 0xfcb00000 if DEBUG_HI3620_UART
default 0xfd883000 if DEBUG_ALPINE_UART0
@@ -1559,7 +1568,7 @@ config DEBUG_UART_PHYS
DEBUG_S3C64XX_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
- DEBUG_AT91_UART
+ DEBUG_AT91_UART || DEBUG_FH_UART
config DEBUG_UART_VIRT
hex "Virtual base address of debug UART"
@@ -1618,6 +1627,7 @@ config DEBUG_UART_VIRT
default 0xfe230000 if DEBUG_PICOXCELL_UART
default 0xfe300000 if DEBUG_BCM_KONA_UART
default 0xfe800000 if ARCH_IOP32X
+ default 0xfe020000 if DEBUG_FH_UART
default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HIX5HD2_UART
default 0xfeb24000 if DEBUG_RK3X_UART0
default 0xfeb26000 if DEBUG_RK3X_UART1
@@ -1658,7 +1668,7 @@ config DEBUG_UART_VIRT
DEBUG_S3C64XX_UART || \
DEBUG_BCM63XX_UART || DEBUG_ASM9260_UART || \
DEBUG_SIRFSOC_UART || DEBUG_DIGICOLOR_UA0 || \
- DEBUG_AT91_UART
+ DEBUG_AT91_UART || DEBUG_FH_UART
config DEBUG_UART_8250_SHIFT
int "Register offset shift for the 8250 debug UART"
@@ -1712,7 +1722,7 @@ config DEBUG_UNCOMPRESS
config UNCOMPRESS_INCLUDE
string
default "debug/uncompress.h" if ARCH_MULTIPLATFORM || ARCH_MSM || \
- PLAT_SAMSUNG || ARM_SINGLE_ARMV7M
+ PLAT_SAMSUNG || ARM_SINGLE_ARMV7M || ARCH_FULLHAN
default "mach/uncompress.h"
config EARLY_PRINTK
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6be9ee14..84e44cf6 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -167,6 +167,7 @@ machine-$(CONFIG_ARCH_EFM32) += efm32
machine-$(CONFIG_ARCH_EP93XX) += ep93xx
machine-$(CONFIG_ARCH_EXYNOS) += exynos
machine-$(CONFIG_ARCH_FOOTBRIDGE) += footbridge
+machine-$(CONFIG_ARCH_FULLHAN) += fh
machine-$(CONFIG_ARCH_GEMINI) += gemini
machine-$(CONFIG_ARCH_HIGHBANK) += highbank
machine-$(CONFIG_ARCH_HISI) += hisi
@@ -258,12 +259,23 @@ endif
machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
platdirs := $(patsubst %,arch/arm/plat-%/,$(sort $(plat-y)))
+ifeq ($(CONFIG_ARCH_FULLHAN),y)
+CONFIG_FH_CHIP_NAME := $(subst ",,$(CONFIG_FH_CHIP_NAME))
+fhdirs := $(patsubst %,arch/arm/mach-fh/%,$(CONFIG_FH_CHIP_NAME))
+endif
+
ifneq ($(CONFIG_ARCH_MULTIPLATFORM),y)
ifneq ($(CONFIG_ARM_SINGLE_ARMV7M),y)
ifeq ($(KBUILD_SRC),)
KBUILD_CPPFLAGS += $(patsubst %,-I%include,$(machdirs) $(platdirs))
+ifeq ($(CONFIG_ARCH_FULLHAN),y)
+KBUILD_CPPFLAGS += $(patsubst %,-I%,$(fhdirs))
+endif
else
KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs) $(platdirs))
+ifeq ($(CONFIG_ARCH_FULLHAN),y)
+KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%,$(fhdirs))
+endif
endif
endif
endif
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 50f8d1be..a8829f8c 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -49,11 +49,17 @@ $(obj)/xipImage: FORCE
$(obj)/Image: vmlinux FORCE
$(call if_changed,objcopy)
+# just copy Image to zImage when build a no compressed uImage
+ifeq ($(CONFIG_KERNEL_NO_COMPRESS),y)
+$(obj)/zImage: $(obj)/Image FORCE
+ @cp $(obj)/Image $(obj)/zImage
+else
$(obj)/compressed/vmlinux: $(obj)/Image FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
+endif
endif
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index fc6d5415..8c828e36 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -218,6 +218,12 @@ not_angel:
addcc r0, r0, pc
cmpcc r4, r0
orrcc r4, r4, #1 @ remember we skipped cache_on
+#if defined (CONFIG_CPU_V7)
+ /* remember in arm cortex-a7 all mmu facility is based on SMP bit */
+ mrc p15, 0, r0, c1, c0, 1
+ orr r0, #(1 << 6)
+ mcr p15, 0, r0, c1, c0, 1
+#endif
blcs cache_on
restart: adr r0, LC0
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index 81c49315..61ae411f 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -78,7 +78,7 @@ SECTIONS
. = BSS_START;
__bss_start = .;
- .bss : { *(.bss) }
+ .bss : { *(.bss) *(.bss.*) }
_end = .;
. = ALIGN(8); /* the stack must be 64-bit aligned */
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7037201c..e6323859 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -161,6 +161,12 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
exynos5440-sd5v1.dtb \
exynos5440-ssdk5440.dtb \
exynos5800-peach-pi.dtb
+dtb-$(CONFIG_MACH_FH8856V200) += fh8856v200.dtb
+dtb-$(CONFIG_MACH_FH8852V200) += fh8852v200.dtb
+dtb-$(CONFIG_MACH_FH8858V200) += fh8858v200.dtb
+dtb-$(CONFIG_MACH_FH8856V210) += fh8856v210.dtb
+dtb-$(CONFIG_MACH_FH8852V210) += fh8852v210.dtb
+dtb-$(CONFIG_MACH_FH8858V210) += fh8858v210.dtb
dtb-$(CONFIG_ARCH_HI3xxx) += \
hi3620-hi4511.dtb
dtb-$(CONFIG_ARCH_HIGHBANK) += \
diff --git a/arch/arm/boot/dts/fh8852v200.dts b/arch/arm/boot/dts/fh8852v200.dts
new file mode 100644
index 00000000..31f53cbd
--- /dev/null
+++ b/arch/arm/boot/dts/fh8852v200.dts
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2017 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+/include/ "fh8852v200_pinctrl.dtsi"
+/ {
+
+
+ model = "FULLHAN FH8852V200";
+ compatible = "fh,fh8852v200";
+ interrupt-parent = <&intc>;
+ aliases {
+ i2c0 = &i2cbus0;
+ i2c1 = &i2cbus1;
+ i2c2 = &i2cbus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ ttyS0 = &serial0;
+ ttyS1 = &serial1;
+ ttyS2 = &serial2;
+ };
+
+ cpus {
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,arm1176jzf-s";
+ };
+ };
+
+ chosen {
+ bootargs = "coherent_pool=2M";
+ };
+
+ intc: interrupt-controller@E0200000 {
+ compatible = "fh,fh-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xE0200000 0x1000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pmu@f0000000 {
+ compatible = "fh,fh-pmu";
+ reg = <0xf0000000 0x2100>;
+ SWRST_MAIN_CTRL = <0x40>;
+ };
+ timer0: timer@f0c00000 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00000 0x14>;
+ };
+
+ timer1: timer@f0c00014 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00014 0x14>;
+ };
+
+ gpio0: gpio@f0300000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf0300000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <26>;
+ id = <0>;
+ ngpio = <32>;
+ base = <0>;
+ };
+
+ gpio1: gpio@f4000000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf4000000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <40>;
+ id = <1>;
+ ngpio = <32>;
+ base = <32>;
+ };
+
+ fhdma0: dma@e0300000 {
+ compatible = "fh,fh-axi-dmac";
+ reg = <0xe0300000 0x1000>;
+ interrupts = <23>;
+ chan_allocation_order = <0>;
+ chan_priority = <1>;
+ block_size = <0x800>;
+ data_width = <2 0 0 0>;
+ clocks = <&ahb_clk>;
+ };
+
+ aes: aes@0xe8200000 {
+ compatible = "fh,fh-aes";
+ reg = <0xe8200000 0x1000>;
+ interrupts = <16>;
+ };
+ rtc: rtc@f1500000 {
+ compatible = "fh,fh_rtc";
+ reg = <0xf1500000 0x1000>;
+ interrupts = <33>;
+ clocks = <&rtc_hclk_gate>;
+ lut_cof = <58>;
+ lut_offset = <0xff>;
+ tsensor_cp_default_out = <0x993>;
+ };
+ sadc: sadc@f1200000 {
+ compatible = "fh,fh-sadc";
+ reg = <0xf1200000 0x1000>;
+ interrupts = <20>;
+ ref-vol = <1800>;
+ active-bit = <0xfff>;
+ };
+ efuse: efuse@0xf1600000 {
+ compatible = "fh,fh-efuse";
+ reg = <0xf1600000 0x1000>;
+ key_switch = "enable";
+ indep_power = "enable";
+ };
+ fh_perf: fh_perf@0xf0002018 {
+ compatible = "fh,fh-perf";
+ reg = <0xf0000000 0x4000>;
+ interrupts = < 5 >;
+
+ };
+ spi_bus0: spi@f0500000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0500000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <6>;
+ cs1_gpio = <55>;
+ dma_enable = "disable";
+ swap_support = "enable";
+ rx_hs_no = <4>;
+ tx_hs_no = <5>;
+ bus_no = <0>;
+ multi_wire_size = <2>;
+ clk_name = "spi0_clk";
+ rx_dma_channel = <0>;
+ tx_dma_channel = <1>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <28>;
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fh,m25p80";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ reg = <0x0 0>; //first value means which slave bind to the master. 0 means chip 0. 1 means chip 1
+ partition@0 {
+ reg = <0x0 0x40000>;
+ label = "bootstrap";
+ };
+ partition@40000 {
+ reg = <0x40000 0x10000>;
+ label = "uboot-env";
+ };
+ partition@50000 {
+ reg = <0x50000 0x30000>;
+ label = "uboot";
+ };
+ partition@80000 {
+ reg = <0x80000 0x400000>;
+ label = "kernel";
+ };
+ partition@480000 {
+ reg = <0x480000 0x80000>;
+ label = "rootfs";
+ };
+ partition@500000 {
+ reg = <0x500000 0x300000>;
+ label = "app";
+ };
+
+ };
+ spidev0: spi@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ spi_bus1: spi@f0600000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0600000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <14>;
+ cs1_gpio = <57>;
+ dma_enable = "disable";
+ swap_support = "disable";
+ rx_hs_no = <2>;
+ tx_hs_no = <3>;
+ bus_no = <1>;
+ clk_name = "spi1_clk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <21>;
+ spidev1: spi@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x0 0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev2: spi@2 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ fhdwi2s: i2s@f0900000 {
+ compatible = "fh,fh-dw_i2s";
+ reg = <0xf0900000 0x1000>;
+ interrupts = <25>;
+ clocks = <&i2s_clk>, <&ac_clk>;
+ clock-names = "i2s_clk", "acodec_mclk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ dma_master = <0>;
+ dma_rx_hs_num = <10>;
+ dma_tx_hs_num = <11>;
+ };
+
+ fhacw: acw@f0a00000 {
+ compatible = "fh,fh-acw";
+ reg = <0xf0a00000 0x1000>;
+ interrupts = <19>;
+ clocks = <&ac_clk>;
+ clock-names = "ac_clk";
+ rx_dma_channel = <4>;
+ tx_dma_channel = <5>;
+ dma_master = <0>;
+ dma_rx_hs_num = <0>;
+ dma_tx_hs_num = <1>;
+ };
+
+ pwm: pwm@f0400000{
+ compatible = "fh,fh-pwm";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <36>;
+ npwm = <14>;
+ };
+ serial0: serial@f0700000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0700000 0x1000>;
+ interrupts = <30>;
+ clock-frequency = <16666667>;
+ fifo-size = <32>;
+ };
+ serial1: serial@f0800000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0800000 0x1000>;
+ interrupts = <31>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ serial2: serial@f1300000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf1300000 0x1000>;
+ interrupts = <41>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ gmac0: gmac@e0600000 {
+ compatible = "fh,fh-gmac";
+ reg = <0xe0600000 0x2000>;
+ interrupts = <44>;
+ phyreset-gpio = <29>;
+ };
+ sdc0: sdc0@e2000000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2000000 0x4000>;
+ interrupts = <42>;
+ id = <0>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <0>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <0>;
+ };
+ sdc1: sdc1@e2200000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2200000 0x4000>;
+ interrupts = <43>;
+ id = <1>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <1>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <2>;
+ };
+ wdt: wdt@f0d00000{
+ compatible = "fh,fh-wdt";
+ reg = <0xf0d00000 0x1000>;
+ interrupts = <2>;
+ mode = <1>;
+ };
+ i2cbus0: i2c@f0200000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0200000 0x2000>;
+ interrupts = <11>;
+ };
+ i2cbus1: i2c@f0b00000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0b00000 0x2000>;
+ interrupts = <12>;
+ };
+ i2cbus2: i2c@0xF0100000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xF0100000 0x2000>;
+ interrupts = <46>;
+ };
+ clocks: src_clk@0xf0000000{
+ compatible = "fh,fh-clk";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf0000000 0x80>;
+ ranges;
+
+ osc_clk: mxtal@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_clk";
+ };
+
+ pll_ddr_rclk: pllddrr{
+ #clock-cells = <0>;
+ compatible = "fh pll-ddr-rclk";
+ reg = <0xf0000010 0x4>,<0xf0000018 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_ddr_rclk";
+ };
+ pll_cpu_pclk: pllcpup{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-pclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_pclk";
+ };
+ pll_cpu_rclk: pllcpur{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-rclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_rclk";
+ };
+ pll_sys_pclk: pllsysp{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-pclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_pclk";
+ };
+ pll_sys_rclk: pllsysr{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-rclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_rclk";
+ };
+ sysp_div12_clk: syspdiv12clk{
+ #clock-cells = <0>;
+ compatible = "fh sysp-div12-clk";
+ reg = <0xf0000038 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sysp_div12_clk";
+ };
+ ddr_clk: ddrclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ddr-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clocks = <&pll_ddr_rclk>;
+ clock-output-names = "ddr_clk";
+ };
+ arm_clk: armclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arm-clk";
+ reg = <0x0 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_pclk>;
+ clock-output-names = "arm_clk";
+ };
+ arc_clk: arcclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arc-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ gate = <0x4000000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_rclk>;
+ clock-output-names = "arc_clk";
+ };
+ ahb_clk: ahbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ahb-clk";
+ reg = <0xf0000024 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ div = <0xf0000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_sys_pclk>;
+ clock-output-names = "ahb_clk";
+ };
+ isp_aclk: ispaclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispa-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00>;
+ gate = <0x1>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "isp_aclk";
+ };
+ ispb_aclk: ispbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispb-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "ispb_aclk";
+ };
+ vpu_clk: vpuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80000000>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "vpu_clk";
+ };
+ pix_clk: pixclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-pix-clk";
+ reg = <0xf000002c 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "pix_clk";
+ };
+ jpeg_clk: jpegclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-clk";
+ reg = <0xf000005c 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "jpeg_clk";
+ };
+ bgm_clk: bgmclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "bgm_clk";
+ };
+ jpeg_adapt_clk: jpegadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-adapt-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2>;
+ clocks = <&jpeg_clk>;
+ clock-output-names = "jpeg_adapt_clk";
+ };
+ spi0_clk: spi0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x80>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi0_clk";
+ };
+ sdc0_clk: sdc0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf00>;
+ gate = <0x200>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc0_clk";
+ };
+ spi2_clk: spi2clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi2-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000>;
+ gate = <0x2>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi2_clk";
+ };
+ spi1_clk: spi1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x100>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi1_clk";
+ };
+ sdc1_clk: sdc1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf000000>;
+ gate = <0x400>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc1_clk";
+ };
+ veu_clk: veuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ div = <0x7000000>;
+ gate = <0x10>;
+ mux = <0x4>;
+ clocks = <&pll_sys_pclk>,<&pll_sys_rclk>;
+ clock-output-names = "veu_clk";
+ };
+ veu_adapt_clk: veuadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-adapt-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clocks = <&veu_clk>;
+ clock-output-names = "veu_adapt_clk";
+ };
+ cis_clk_out: cisclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-cis-clk-out";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x800000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "cis_clk_out";
+ };
+ eth_clk: ethclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-eth-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ gate = <0x2000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "eth_clk";
+ };
+ eth_rmii_clk: ethrmiiclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ethrmii-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "eth_rmii_clk";
+ };
+ i2c0_clk: i2c0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f0000>;
+ gate = <0x1000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c0_clk";
+ };
+
+ i2c1_clk: i2c1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x8000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c1_clk";
+ };
+ i2c2_clk: i2c2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x00000008>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c2_clk";
+ };
+
+ uart0_clk: uart0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f>;
+ gate = <0x2000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart0_clk";
+ };
+
+ uart1_clk: uart1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f00>;
+ gate = <0x4000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart1_clk";
+ };
+ uart2_clk: uart2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f>;
+ gate = <0x8000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart2_clk";
+ };
+ pwm_clk: pwmclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pwm-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x10000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pwm_clk";
+ };
+ efuse_clk: efuseclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-efuse-clk";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x200000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "efuse_clk";
+ };
+ pts_clk: ptsclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pts-clk";
+ reg = <0xf000002c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1ff>;
+ gate = <0x80000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pts_clk";
+ };
+ tmr0_clk: tmr0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-tmr0-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x20000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "tmr0_clk";
+ };
+
+ sadc_clk: sadcclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sadc-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f0000>;
+ gate = <0x4000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "sadc_clk";
+ };
+ gpio0_dbclk: gpio0dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff>;
+ gate = <0x8000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio0_dbclk";
+ };
+ gpio1_dbclk: gpio1dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff0000>;
+ gate = <0x80000000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio1_dbclk";
+ };
+ wdt_clk: wdtclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-wdt-clk";
+ reg = <0xf0000038 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xff00>;
+ gate = <0x8000000>;
+ clocks = <&ahb_clk>;
+ clock-output-names = "wdt_clk";
+ };
+ ac_clk: acclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ac-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f>;
+ gate = <0x800>;
+ clocks = <&osc_clk>;
+ clock-output-names = "ac_clk";
+ };
+ i2s_clk: i2sclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-i2s-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x1000000>;
+ clocks = <&ac_clk>;
+ clock-output-names = "i2s_clk";
+ };
+ mipi_dphy_clk: mipidphyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-dphy-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x100000>;
+ clock-output-names = "mipi_dphy_clk";
+ };
+ mipi_wrap_gate: mipiwrapclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-wrap-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "mipi_wrap_gate";
+ };
+ rtc_hclk_gate: rtchclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-rtc-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "rtc_hclk_gate";
+ };
+ emac_hclk_gate: emachclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-emac-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "emac_hclk_gate";
+ };
+ usb_clk: usbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-usb-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "usb_clk";
+ };
+ aes_hclk_gate: aeshclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-aes-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80>;
+ clock-output-names = "aes_hclk_gate";
+ };
+ ephy_clk_gate: ephyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ephy-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1>;
+ clock-output-names = "ephy_clk_gate";
+ };
+ sdc0_clk8x_gate: sdc08xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc08x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clock-output-names = "sdc0_clk8x_gate";
+ };
+ sdc1_clk8x_gate: sdc18xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc18x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x8>;
+ clock-output-names = "sdc1_clk8x_gate";
+ };
+ mipic_pclk_gate: mipicpclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipic-pclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10>;
+ clock-output-names = "mipic_pclk_gate";
+ };
+ gpio0_pclk_gate: gpio0pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x4000>;
+ clock-output-names = "gpio0_pclk_gate";
+ };
+ gpio1_pclk_gate: gpio1pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "gpio1_pclk_gate";
+ };
+ isp_hclk_gate: isphclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-isp-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "isp_hclk_gate";
+ };
+ veu_hclk_gate: veuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "veu_hclk_gate";
+ };
+ bgm_hclk_gate: bgmhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clock-output-names = "bgm_hclk_gate";
+ };
+ adapt_hclk_gate: adapthclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-adapt-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x8000000>;
+ clock-output-names = "adapt_hclk_gate";
+ };
+ jpg_hclk_gate: jpghclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "jpg_hclk_gate";
+ };
+ jpg_adapt_gate: jpgadaptclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-adapt-clk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "jpg_adapt_gate";
+ };
+ vpu_hclk_gate: vpuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "vpu_hclk_gate";
+ };
+ sdc0_clk_sample: sdc0clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf0000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_sample";
+ };
+ sdc0_clk_drv: sdc0clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_drv";
+ };
+
+ sdc1_clk_sample: sdc1clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_sample";
+ };
+
+ sdc1_clk_drv: sdc1clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf000>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_drv";
+ };
+ };
+ };
+
+ usb_otg@e0700000 {
+ compatible = "fh_usb";
+ reg = <0xe0700000 100000>;
+ interrupts = <39>;
+ clocks = <&usb_clk>;
+ dr_mode = "host";
+ vbus_pwren = <47>;
+ clock-names = "otg";
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
+ };
+
+ usb2_phy: usbphy {
+ compatible = "fh,fh-usb2-phy";
+ #phy-cells = <0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/fh8852v200_pinctrl.dtsi b/arch/arm/boot/dts/fh8852v200_pinctrl.dtsi
new file mode 100644
index 00000000..195479e3
--- /dev/null
+++ b/arch/arm/boot/dts/fh8852v200_pinctrl.dtsi
@@ -0,0 +1,2386 @@
+/*
+ * Copyright (C) 2020 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ #define PUPD_NONE (0)
+ #define PUPD_UP (1)
+ #define PUPD_DOWN (2)
+*/
+
+/ {
+ pinctrl: pinctrl@f0000080 {
+ compatible = "fh,fh-pinctrl";
+ reg = <0xf0000080 0x104>;
+ pad-num = <65>;
+ max-mux = <9>;
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_ETH
+ &pinctrl_I2C0
+ &pinctrl_PWM2
+ &pinctrl_PWM3
+ &pinctrl_PWM4
+ &pinctrl_PWM5
+ &pinctrl_PWM6
+ &pinctrl_PWM7
+ &pinctrl_PWM8
+ &pinctrl_PWM9
+ &pinctrl_SADC_XAIN0
+ &pinctrl_SADC_XAIN1
+ &pinctrl_SD0_NO_WP
+ &pinctrl_SENSOR_CLK
+ &pinctrl_SSI0_4BIT
+ &pinctrl_UART0
+ &pinctrl_UART1
+ &pinctrl_GPIO4
+ &pinctrl_GPIO13
+ &pinctrl_GPIO30
+ &pinctrl_GPIO31
+ &pinctrl_GPIO32
+ &pinctrl_GPIO43
+ &pinctrl_GPIO44
+ &pinctrl_GPIO47
+
+ &pinctrl_GPIO11
+ &pinctrl_GPIO14
+ &pinctrl_GPIO15
+ &pinctrl_GPIO16
+ &pinctrl_GPIO24
+ &pinctrl_GPIO25
+ &pinctrl_GPIO45
+ &pinctrl_GPIO46
+ &pinctrl_GPIO48
+ &pinctrl_GPIO49
+ &pinctrl_GPIO50
+ &pinctrl_GPIO51
+ &pinctrl_GPIO52
+ &pinctrl_GPIO53
+ &pinctrl_GPIO54
+ &pinctrl_GPIO55
+ &pinctrl_GPIO56
+ &pinctrl_GPIO57
+ &pinctrl_GPIO58
+ &pinctrl_GPIO59
+ &pinctrl_GPIO60
+ &pinctrl_GPIO61
+ &pinctrl_GPIO62
+ &pinctrl_GPIO63
+ >;
+ pinctrl_groups {
+ pinctrl_ACI2S: ACI2S {
+ fh,pins = <
+ &mux_AC_I2S_CLK 0
+ &mux_AC_I2S_DI 0
+ &mux_AC_I2S_DO 0
+ &mux_AC_I2S_WS 0
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_AC_MCLK: AC_MCLK {
+ fh,pins = <
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_ARCJTAG: ARCJTAG {
+ fh,pins = <
+ &mux_ARC_JTAG_TCK 0
+ &mux_ARC_JTAG_TDI 0
+ &mux_ARC_JTAG_TDO 0
+ &mux_ARC_JTAG_TMS 0
+ &mux_ARC_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_ARMJTAG: ARMJTAG {
+ fh,pins = <
+ &mux_ARM_JTAG_TCK 0
+ &mux_ARM_JTAG_TDI 0
+ &mux_ARM_JTAG_TDO 0
+ &mux_ARM_JTAG_TMS 0
+ &mux_ARM_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_DWI2S: DWI2S {
+ fh,pins = <
+ &mux_DW_I2S_CLK 0
+ &mux_DW_I2S_DI 0
+ &mux_DW_I2S_DO 0
+ &mux_DW_I2S_WS 0
+ >;
+ };
+ pinctrl_ETH: ETH {
+ fh,pins = <
+ &mux_ETH_LINK_ACT 1
+ &mux_ETH_LINK_STA 1
+ >;
+ };
+ pinctrl_I2C0: I2C0 {
+ fh,pins = <
+ &mux_I2C0_SCL 0
+ &mux_I2C0_SDA 0
+ >;
+ };
+ pinctrl_I2C1: I2C1 {
+ fh,pins = <
+ &mux_I2C1_SCL 2
+ &mux_I2C1_SDA 2
+ >;
+ };
+ pinctrl_I2C2: I2C2 {
+ fh,pins = <
+ &mux_I2C2_SCL 1
+ &mux_I2C2_SDA 1
+ >;
+ };
+ pinctrl_PAEJTAG: PAEJTAG {
+ fh,pins = <
+ &mux_PAE_JTAG_TCK 0
+ &mux_PAE_JTAG_TDI 0
+ &mux_PAE_JTAG_TDO 0
+ &mux_PAE_JTAG_TMS 0
+ &mux_PAE_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_PWM0: PWM0 {
+ fh,pins = <
+ &mux_PWM0 0
+ >;
+ };
+ pinctrl_PWM1: PWM1 {
+ fh,pins = <
+ &mux_PWM1 0
+ >;
+ };
+ pinctrl_PWM10: PWM10 {
+ fh,pins = <
+ &mux_PWM10 0
+ >;
+ };
+ pinctrl_PWM11: PWM11 {
+ fh,pins = <
+ &mux_PWM11 0
+ >;
+ };
+ pinctrl_PWM2: PWM2 {
+ fh,pins = <
+ &mux_PWM2 0
+ >;
+ };
+ pinctrl_PWM3: PWM3 {
+ fh,pins = <
+ &mux_PWM3 0
+ >;
+ };
+ pinctrl_PWM4: PWM4 {
+ fh,pins = <
+ &mux_PWM4 0
+ >;
+ };
+ pinctrl_PWM5: PWM5 {
+ fh,pins = <
+ &mux_PWM5 0
+ >;
+ };
+ pinctrl_PWM6: PWM6 {
+ fh,pins = <
+ &mux_PWM6 1
+ >;
+ };
+ pinctrl_PWM7: PWM7 {
+ fh,pins = <
+ &mux_PWM7 1
+ >;
+ };
+ pinctrl_PWM8: PWM8 {
+ fh,pins = <
+ &mux_PWM8 1
+ >;
+ };
+ pinctrl_PWM9: PWM9 {
+ fh,pins = <
+ &mux_PWM9 1
+ >;
+ };
+ pinctrl_RMII: RMII {
+ fh,pins = <
+ &mux_MAC_MDC 1
+ &mux_MAC_MDIO 1
+ &mux_MAC_REF_CLK 0
+ &mux_MAC_RMII_CLK 0
+ &mux_MAC_RXDV 0
+ &mux_MAC_RXD_0 0
+ &mux_MAC_RXD_1 0
+ &mux_MAC_TXD_0 0
+ &mux_MAC_TXD_1 0
+ &mux_MAC_TXEN 0
+ >;
+ };
+ pinctrl_RTC: RTC {
+ fh,pins = <
+ &mux_RTC_CLK 0
+ >;
+ };
+ pinctrl_SADC_XAIN0: SADC_XAIN0 {
+ fh,pins = <
+ &mux_SADC_XAIN0 0
+ >;
+ };
+ pinctrl_SADC_XAIN1: SADC_XAIN1 {
+ fh,pins = <
+ &mux_SADC_XAIN1 0
+ >;
+ };
+ pinctrl_SADC_XAIN2: SADC_XAIN2 {
+ fh,pins = <
+ &mux_SADC_XAIN2 0
+ >;
+ };
+ pinctrl_SADC_XAIN3: SADC_XAIN3 {
+ fh,pins = <
+ &mux_SADC_XAIN3 0
+ >;
+ };
+ pinctrl_SD0: SD0 {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_1BIT_NO_WP: SD0_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ >;
+ };
+ pinctrl_SD0_NO_WP: SD0_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_WIFI: SD0_WIFI {
+ fh,pins = <
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD1: SD1 {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_1BIT_NO_WP: SD1_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ >;
+ };
+ pinctrl_SD1_NO_WP: SD1_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_WIFI: SD1_WIFI {
+ fh,pins = <
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SENSOR_CLK: SENSOR_CLK {
+ fh,pins = <
+ &mux_SENSOR_CLK 0
+ >;
+ };
+ pinctrl_SSI0: SSI0 {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI0_4BIT: SSI0_4BIT {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_D2 0
+ &mux_SSI0_D3 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI1: SSI1 {
+ fh,pins = <
+ &mux_GPIO14 0
+ &mux_SSI1_CLK 2
+ &mux_SSI1_RXD 2
+ &mux_SSI1_TXD 2
+ >;
+ };
+ pinctrl_SSI2: SSI2 {
+ fh,pins = <
+ &mux_SSI2_CLK 1
+ &mux_SSI2_CSN_0 1
+ &mux_SSI2_RXD 1
+ &mux_SSI2_TXD 1
+ >;
+ };
+ pinctrl_UART0: UART0 {
+ fh,pins = <
+ &mux_UART0_RX 0
+ &mux_UART0_TX 0
+ >;
+ };
+ pinctrl_UART1: UART1 {
+ fh,pins = <
+ &mux_UART1_RX 0
+ &mux_UART1_TX 0
+ >;
+ };
+ pinctrl_UART2: UART2 {
+ fh,pins = <
+ &mux_UART2_RX 0
+ &mux_UART2_TX 0
+ >;
+ };
+ pinctrl_USB: USB {
+ fh,pins = <
+ &mux_USB_PWREN 0
+ >;
+ };
+ pinctrl_GPIO0: GPIO0 {
+ fh,pins = <
+ &mux_GPIO0 0
+ >;
+ };
+ pinctrl_GPIO1: GPIO1 {
+ fh,pins = <
+ &mux_GPIO1 0
+ >;
+ };
+ pinctrl_GPIO2: GPIO2 {
+ fh,pins = <
+ &mux_GPIO2 0
+ >;
+ };
+ pinctrl_GPIO3: GPIO3 {
+ fh,pins = <
+ &mux_GPIO3 0
+ >;
+ };
+ pinctrl_GPIO4: GPIO4 {
+ fh,pins = <
+ &mux_GPIO4 0
+ >;
+ };
+ pinctrl_GPIO5: GPIO5 {
+ fh,pins = <
+ &mux_GPIO5 0
+ >;
+ };
+ pinctrl_GPIO6: GPIO6 {
+ fh,pins = <
+ &mux_GPIO6 0
+ >;
+ };
+ pinctrl_GPIO7: GPIO7 {
+ fh,pins = <
+ &mux_GPIO7 0
+ >;
+ };
+ pinctrl_GPIO8: GPIO8 {
+ fh,pins = <
+ &mux_GPIO8 0
+ >;
+ };
+ pinctrl_GPIO9: GPIO9 {
+ fh,pins = <
+ &mux_GPIO9 0
+ >;
+ };
+ pinctrl_GPIO10: GPIO10 {
+ fh,pins = <
+ &mux_GPIO10 0
+ >;
+ };
+ pinctrl_GPIO11: GPIO11 {
+ fh,pins = <
+ &mux_GPIO11 0
+ >;
+ };
+ pinctrl_GPIO12: GPIO12 {
+ fh,pins = <
+ &mux_GPIO12 0
+ >;
+ };
+ pinctrl_GPIO13: GPIO13 {
+ fh,pins = <
+ &mux_GPIO13 0
+ >;
+ };
+ pinctrl_GPIO14: GPIO14 {
+ fh,pins = <
+ &mux_GPIO14 0
+ >;
+ };
+ pinctrl_GPIO15: GPIO15 {
+ fh,pins = <
+ &mux_GPIO15 0
+ >;
+ };
+ pinctrl_GPIO16: GPIO16 {
+ fh,pins = <
+ &mux_GPIO16 0
+ >;
+ };
+ pinctrl_GPIO17: GPIO17 {
+ fh,pins = <
+ &mux_GPIO17 0
+ >;
+ };
+ pinctrl_GPIO18: GPIO18 {
+ fh,pins = <
+ &mux_GPIO18 0
+ >;
+ };
+ pinctrl_GPIO19: GPIO19 {
+ fh,pins = <
+ &mux_GPIO19 0
+ >;
+ };
+ pinctrl_GPIO20: GPIO20 {
+ fh,pins = <
+ &mux_GPIO20 0
+ >;
+ };
+ pinctrl_GPIO21: GPIO21 {
+ fh,pins = <
+ &mux_GPIO21 0
+ >;
+ };
+ pinctrl_GPIO22: GPIO22 {
+ fh,pins = <
+ &mux_GPIO22 0
+ >;
+ };
+ pinctrl_GPIO23: GPIO23 {
+ fh,pins = <
+ &mux_GPIO23 0
+ >;
+ };
+ pinctrl_GPIO24: GPIO24 {
+ fh,pins = <
+ &mux_GPIO24 0
+ >;
+ };
+ pinctrl_GPIO25: GPIO25 {
+ fh,pins = <
+ &mux_GPIO25 0
+ >;
+ };
+ pinctrl_GPIO26: GPIO26 {
+ fh,pins = <
+ &mux_GPIO26 0
+ >;
+ };
+ pinctrl_GPIO27: GPIO27 {
+ fh,pins = <
+ &mux_GPIO27 0
+ >;
+ };
+ pinctrl_GPIO28: GPIO28 {
+ fh,pins = <
+ &mux_GPIO28 0
+ >;
+ };
+ pinctrl_GPIO29: GPIO29 {
+ fh,pins = <
+ &mux_GPIO29 0
+ >;
+ };
+ pinctrl_GPIO30: GPIO30 {
+ fh,pins = <
+ &mux_GPIO30 0
+ >;
+ };
+ pinctrl_GPIO31: GPIO31 {
+ fh,pins = <
+ &mux_GPIO31 0
+ >;
+ };
+ pinctrl_GPIO32: GPIO32 {
+ fh,pins = <
+ &mux_GPIO32 0
+ >;
+ };
+ pinctrl_GPIO33: GPIO33 {
+ fh,pins = <
+ &mux_GPIO33 0
+ >;
+ };
+ pinctrl_GPIO34: GPIO34 {
+ fh,pins = <
+ &mux_GPIO34 0
+ >;
+ };
+ pinctrl_GPIO35: GPIO35 {
+ fh,pins = <
+ &mux_GPIO35 0
+ >;
+ };
+ pinctrl_GPIO36: GPIO36 {
+ fh,pins = <
+ &mux_GPIO36 0
+ >;
+ };
+ pinctrl_GPIO37: GPIO37 {
+ fh,pins = <
+ &mux_GPIO37 0
+ >;
+ };
+ pinctrl_GPIO38: GPIO38 {
+ fh,pins = <
+ &mux_GPIO38 0
+ >;
+ };
+ pinctrl_GPIO39: GPIO39 {
+ fh,pins = <
+ &mux_GPIO39 0
+ >;
+ };
+ pinctrl_GPIO40: GPIO40 {
+ fh,pins = <
+ &mux_GPIO40 0
+ >;
+ };
+ pinctrl_GPIO41: GPIO41 {
+ fh,pins = <
+ &mux_GPIO41 0
+ >;
+ };
+ pinctrl_GPIO42: GPIO42 {
+ fh,pins = <
+ &mux_GPIO42 0
+ >;
+ };
+ pinctrl_GPIO43: GPIO43 {
+ fh,pins = <
+ &mux_GPIO43 0
+ >;
+ };
+ pinctrl_GPIO44: GPIO44 {
+ fh,pins = <
+ &mux_GPIO44 0
+ >;
+ };
+ pinctrl_GPIO45: GPIO45 {
+ fh,pins = <
+ &mux_GPIO45 0
+ >;
+ };
+ pinctrl_GPIO46: GPIO46 {
+ fh,pins = <
+ &mux_GPIO46 0
+ >;
+ };
+ pinctrl_GPIO47: GPIO47 {
+ fh,pins = <
+ &mux_GPIO47 0
+ >;
+ };
+ pinctrl_GPIO48: GPIO48 {
+ fh,pins = <
+ &mux_GPIO48 0
+ >;
+ };
+ pinctrl_GPIO49: GPIO49 {
+ fh,pins = <
+ &mux_GPIO49 0
+ >;
+ };
+ pinctrl_GPIO50: GPIO50 {
+ fh,pins = <
+ &mux_GPIO50 0
+ >;
+ };
+ pinctrl_GPIO51: GPIO51 {
+ fh,pins = <
+ &mux_GPIO51 0
+ >;
+ };
+ pinctrl_GPIO52: GPIO52 {
+ fh,pins = <
+ &mux_GPIO52 0
+ >;
+ };
+ pinctrl_GPIO53: GPIO53 {
+ fh,pins = <
+ &mux_GPIO53 0
+ >;
+ };
+ pinctrl_GPIO54: GPIO54 {
+ fh,pins = <
+ &mux_GPIO54 0
+ >;
+ };
+ pinctrl_GPIO55: GPIO55 {
+ fh,pins = <
+ &mux_GPIO55 0
+ >;
+ };
+ pinctrl_GPIO56: GPIO56 {
+ fh,pins = <
+ &mux_GPIO56 0
+ >;
+ };
+ pinctrl_GPIO57: GPIO57 {
+ fh,pins = <
+ &mux_GPIO57 0
+ >;
+ };
+ pinctrl_GPIO58: GPIO58 {
+ fh,pins = <
+ &mux_GPIO58 0
+ >;
+ };
+ pinctrl_GPIO59: GPIO59 {
+ fh,pins = <
+ &mux_GPIO59 0
+ >;
+ };
+ pinctrl_GPIO60: GPIO60 {
+ fh,pins = <
+ &mux_GPIO60 0
+ >;
+ };
+ pinctrl_GPIO61: GPIO61 {
+ fh,pins = <
+ &mux_GPIO61 0
+ >;
+ };
+ pinctrl_GPIO62: GPIO62 {
+ fh,pins = <
+ &mux_GPIO62 0
+ >;
+ };
+ pinctrl_GPIO63: GPIO63 {
+ fh,pins = <
+ &mux_GPIO63 0
+ >;
+ };
+ pinctrl_SD1_EMMC: SD1_EMMC {
+ fh,pins = <
+ &mux_SD1_CD 3
+ &mux_SD1_CLK 3
+ &mux_SD1_CMD_RSP 3
+ &mux_SD1_DATA_0 3
+ &mux_SD1_DATA_1 3
+ &mux_SD1_DATA_2 3
+ &mux_SD1_DATA_3 3
+ >;
+ };
+ };
+ pinmux: pinmux {
+ compatible = "fh,fh-pinmux";
+ #list-cells = <1>;
+ mux_AC_I2S_CLK: AC_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_AC_I2S_DI: AC_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_AC_I2S_DO: AC_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_AC_I2S_WS: AC_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_AC_MCLK: AC_MCLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+
+ mux_ARC_JTAG_TCK: ARC_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_ARC_JTAG_TDI: ARC_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_ARC_JTAG_TDO: ARC_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_ARC_JTAG_TMS: ARC_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_ARC_JTAG_TRSTN: ARC_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_ARM_JTAG_TCK: ARM_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_ARM_JTAG_TDI: ARM_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_ARM_JTAG_TDO: ARM_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_ARM_JTAG_TMS: ARM_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_ARM_JTAG_TRSTN: ARM_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+
+ mux_DW_I2S_CLK: DW_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_DW_I2S_DI: DW_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_DW_I2S_DO: DW_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_DW_I2S_WS: DW_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+
+ mux_ETH_LINK_ACT: ETH_LINK_ACT {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad1
+ &pad63
+ >;
+ };
+ mux_ETH_LINK_SPD: ETH_LINK_SPD {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+ mux_ETH_LINK_STA: ETH_LINK_STA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+
+ mux_I2C0_SCL: I2C0_SCL {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_I2C0_SDA: I2C0_SDA {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+
+ mux_I2C1_SCL: I2C1_SCL {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad11
+ &pad30
+ &pad46
+ >;
+ };
+ mux_I2C1_SDA: I2C1_SDA {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad12
+ &pad31
+ &pad47
+ >;
+ };
+
+ mux_I2C2_SCL: I2C2_SCL {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad16
+ &pad57
+ >;
+ };
+ mux_I2C2_SDA: I2C2_SDA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad17
+ &pad58
+ >;
+ };
+
+ mux_MAC_MDC: MAC_MDC {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad28
+ &pad63
+ >;
+ };
+ mux_MAC_MDIO: MAC_MDIO {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad29
+ &pad64
+ >;
+ };
+ mux_MAC_REF_CLK: MAC_REF_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad21
+ >;
+ };
+ mux_MAC_RMII_CLK: MAC_RMII_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_MAC_RXDV: MAC_RXDV {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_MAC_RXD_0: MAC_RXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_MAC_RXD_1: MAC_RXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_MAC_TXD_0: MAC_TXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_MAC_TXD_1: MAC_TXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_MAC_TXEN: MAC_TXEN {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+
+ mux_PAE_JTAG_TCK: PAE_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_PAE_JTAG_TDI: PAE_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_PAE_JTAG_TDO: PAE_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_PAE_JTAG_TMS: PAE_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_PAE_JTAG_TRSTN: PAE_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_PWM0: PWM0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_PWM1: PWM1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_PWM10: PWM10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_PWM11: PWM11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_PWM2: PWM2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ &pad18
+ &pad20
+ >;
+ };
+ mux_PWM3: PWM3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ &pad19
+ &pad22
+ >;
+ };
+ mux_PWM4: PWM4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad23
+ >;
+ };
+ mux_PWM5: PWM5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad24
+ >;
+ };
+ mux_PWM6: PWM6 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad25
+ &pad37
+ >;
+ };
+ mux_PWM7: PWM7 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad26
+ &pad38
+ >;
+ };
+ mux_PWM8: PWM8 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad27
+ &pad39
+ >;
+ };
+ mux_PWM9: PWM9 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad28
+ &pad40
+ >;
+ };
+
+ mux_RTC_CLK: RTC_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+
+ mux_SADC_XAIN0: SADC_XAIN0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_SADC_XAIN1: SADC_XAIN1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_SADC_XAIN2: SADC_XAIN2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_SADC_XAIN3: SADC_XAIN3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+
+ mux_SD0_CD: SD0_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_SD0_CLK: SD0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_SD0_CMD_RSP: SD0_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_SD0_DATA_0: SD0_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_SD0_DATA_1: SD0_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_SD0_DATA_2: SD0_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_SD0_DATA_3: SD0_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+
+ mux_SD1_CD: SD1_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad10
+ &pad22
+ &pad31
+ &pad41
+ &pad63
+ >;
+ };
+ mux_SD1_CLK: SD1_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad9
+ &pad20
+ &pad30
+ &pad42
+ >;
+ };
+ mux_SD1_CMD_RSP: SD1_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad23
+ &pad32
+ &pad43
+ >;
+ };
+ mux_SD1_DATA_0: SD1_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad12
+ &pad24
+ &pad33
+ &pad44
+ >;
+ };
+ mux_SD1_DATA_1: SD1_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad25
+ &pad34
+ &pad45
+ >;
+ };
+ mux_SD1_DATA_2: SD1_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad26
+ &pad35
+ &pad46
+ >;
+ };
+ mux_SD1_DATA_3: SD1_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad15
+ &pad27
+ &pad36
+ &pad47
+ >;
+ };
+
+ mux_SENSOR_CLK: SENSOR_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+
+ mux_SSI0_CLK: SSI0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_SSI0_D2: SSI0_D2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_SSI0_D3: SSI0_D3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_SSI0_RXD: SSI0_RXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_SSI0_TXD: SSI0_TXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+
+ mux_SSI1_CLK: SSI1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad37
+ &pad48
+ &pad53
+ >;
+ };
+ mux_SSI1_RXD: SSI1_RXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad40
+ &pad51
+ &pad55
+ >;
+ };
+ mux_SSI1_TXD: SSI1_TXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad39
+ &pad50
+ &pad54
+ >;
+ };
+
+ mux_SSI2_CLK: SSI2_CLK {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad37
+ &pad48
+ >;
+ };
+ mux_SSI2_CSN_0: SSI2_CSN_0 {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad38
+ &pad49
+ >;
+ };
+ mux_SSI2_RXD: SSI2_RXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad40
+ &pad51
+ >;
+ };
+ mux_SSI2_TXD: SSI2_TXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad39
+ &pad50
+ >;
+ };
+
+ mux_UART0_RX: UART0_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_UART0_TX: UART0_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+
+ mux_UART1_RX: UART1_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ &pad33
+ &pad47
+ >;
+ };
+ mux_UART1_TX: UART1_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ &pad32
+ &pad46
+ >;
+ };
+
+ mux_UART2_RX: UART2_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad17
+ &pad35
+ &pad58
+ >;
+ };
+ mux_UART2_TX: UART2_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad16
+ &pad34
+ &pad57
+ >;
+ };
+
+ mux_USB_PWREN: USB_PWREN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ &pad41
+ >;
+ };
+
+ mux_GPIO0: GPIO0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_GPIO1: GPIO1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_GPIO2: GPIO2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_GPIO3: GPIO3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_GPIO4: GPIO4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_GPIO5: GPIO5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_GPIO6: GPIO6 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad43
+ >;
+ };
+ mux_GPIO7: GPIO7 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+ mux_GPIO8: GPIO8 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_GPIO9: GPIO9 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_GPIO10: GPIO10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_GPIO11: GPIO11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad48
+ >;
+ };
+ mux_GPIO12: GPIO12 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+ mux_GPIO13: GPIO13 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad8
+ >;
+ };
+ mux_GPIO14: GPIO14 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad49
+ >;
+ };
+ mux_GPIO15: GPIO15 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad50
+ >;
+ };
+ mux_GPIO16: GPIO16 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad51
+ >;
+ };
+ mux_GPIO17: GPIO17 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_GPIO18: GPIO18 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_GPIO19: GPIO19 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_GPIO20: GPIO20 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_GPIO21: GPIO21 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_GPIO22: GPIO22 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_GPIO23: GPIO23 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+ mux_GPIO24: GPIO24 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_GPIO25: GPIO25 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+ mux_GPIO26: GPIO26 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_GPIO27: GPIO27 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_GPIO28: GPIO28 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_GPIO29: GPIO29 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_GPIO30: GPIO30 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad0
+ >;
+ };
+ mux_GPIO31: GPIO31 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad1
+ >;
+ };
+ mux_GPIO32: GPIO32 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad2
+ >;
+ };
+ mux_GPIO33: GPIO33 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+ mux_GPIO34: GPIO34 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_GPIO35: GPIO35 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_GPIO36: GPIO36 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+ mux_GPIO37: GPIO37 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ >;
+ };
+ mux_GPIO38: GPIO38 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ >;
+ };
+ mux_GPIO39: GPIO39 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ >;
+ };
+ mux_GPIO40: GPIO40 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ >;
+ };
+ mux_GPIO41: GPIO41 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ >;
+ };
+ mux_GPIO42: GPIO42 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ >;
+ };
+ mux_GPIO43: GPIO43 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_GPIO44: GPIO44 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_GPIO45: GPIO45 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad18
+ >;
+ };
+ mux_GPIO46: GPIO46 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad19
+ >;
+ };
+ mux_GPIO47: GPIO47 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ >;
+ };
+ mux_GPIO48: GPIO48 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_GPIO49: GPIO49 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_GPIO50: GPIO50 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_GPIO51: GPIO51 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+ mux_GPIO52: GPIO52 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_GPIO53: GPIO53 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_GPIO54: GPIO54 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_GPIO55: GPIO55 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad28
+ >;
+ };
+ mux_GPIO56: GPIO56 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad29
+ >;
+ };
+ mux_GPIO57: GPIO57 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad30
+ >;
+ };
+ mux_GPIO58: GPIO58 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad31
+ >;
+ };
+ mux_GPIO59: GPIO59 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad32
+ >;
+ };
+ mux_GPIO60: GPIO60 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad33
+ >;
+ };
+ mux_GPIO61: GPIO61 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad34
+ >;
+ };
+ mux_GPIO62: GPIO62 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad35
+ >;
+ };
+ mux_GPIO63: GPIO63 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad36
+ >;
+ };
+ };
+ pinpad: pinpad {
+ compatible = "fh,fh-pinpad";
+ pad0: PAD_BOOT_MODE_CFG {
+ index = <0>;
+ funcs = "GPIO30";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad1: PAD_BOOT_SEL1_CFG {
+ index = <1>;
+ funcs = "GPIO31", "ETH_LINK_ACT";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad2: PAD_BOOT_SEL0_CFG {
+ index = <2>;
+ funcs = "GPIO32", "ETH_LINK_STA", "ETH_LINK_SPD";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad3: PAD_UART0_TX_CFG {
+ index = <3>;
+ funcs = "UART0_TX", "GPIO33";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad4: PAD_UART0_RX_CFG {
+ index = <4>;
+ funcs = "UART0_RX", "GPIO34";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad5: PAD_I2C0_SCL_CFG {
+ index = <5>;
+ funcs = "I2C0_SCL", "GPIO35";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad6: PAD_I2C0_SDA_CFG {
+ index = <6>;
+ funcs = "I2C0_SDA", "GPIO36";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad7: PAD_SENSOR_CLK_CFG {
+ index = <7>;
+ funcs = "SENSOR_CLK", "GPIO12";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad8: PAD_SENSOR_RSTN_CFG {
+ index = <8>;
+ funcs = "GPIO13";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad9: PAD_UART1_TX_CFG {
+ index = <9>;
+ funcs = "UART1_TX", "GPIO39", "", "SD1_CLK", "", "",
+ "TEST_O_INT_RMII_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad10: PAD_UART1_RX_CFG {
+ index = <10>;
+ funcs = "UART1_RX", "GPIO40", "", "SD1_CD", "", "",
+ "TEST_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad11: PAD_I2C1_SCL_CFG {
+ index = <11>;
+ funcs = "I2C1_SCL", "GPIO37", "PWM2", "SD1_CMD_RSP", "",
+ "SSI1_CLK", "TEST_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad12: PAD_I2C1_SDA_CFG {
+ index = <12>;
+ funcs = "I2C1_SDA", "GPIO38", "PWM3", "SD1_DATA_0", "",
+ "SSI1_CSN_0", "TEST_INT_RMII_TXEN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad13: PAD_UART2_TX_CFG {
+ index = <13>;
+ funcs = "UART2_TX", "GPIO41", "PWM4", "SD1_DATA_1", "",
+ "SSI1_TXD", "TEST_O_INT_RMII_RXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad14: PAD_UART2_RX_CFG {
+ index = <14>;
+ funcs = "UART2_RX", "GPIO42", "PWM5", "SD1_DATA_2", "",
+ "SSI1_RXD", "TEST_O_INT_RMII_RXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad15: PAD_USB_PWREN_CFG {
+ index = <15>;
+ funcs = "USB_PWREN", "GPIO47", "", "SD1_DATA_3", "", "",
+ "TEST_O_INT_RMII_CRSDV";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad16: PAD_PWM0_CFG {
+ index = <16>;
+ funcs = "PWM0", "GPIO43", "I2C2_SCL", "UART2_TX", "", "",
+ "TEST_O_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad17: PAD_PWM1_CFG {
+ index = <17>;
+ funcs = "PWM1", "GPIO44", "I2C2_SDA", "UART2_RX", "", "",
+ "TEST_O_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad18: PAD_PWM2_CFG {
+ index = <18>;
+ funcs = "PWM2", "GPIO45";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad19: PAD_PWM3_CFG {
+ index = <19>;
+ funcs = "PWM3", "GPIO46";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad20: PAD_MAC_RMII_CLK_CFG {
+ index = <20>;
+ funcs = "MAC_RMII_CLK", "GPIO48", "SD1_CLK", "PWM2";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad21: PAD_MAC_REF_CLK_CFG {
+ index = <21>;
+ funcs = "MAC_REF_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad22: PAD_MAC_TXD0_CFG {
+ index = <22>;
+ funcs = "MAC_TXD_0", "GPIO49", "SD1_CD", "PWM3";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad23: PAD_MAC_TXD1_CFG {
+ index = <23>;
+ funcs = "MAC_TXD_1", "GPIO50", "SD1_CMD_RSP", "PWM4";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad24: PAD_MAC_TXEN_CFG {
+ index = <24>;
+ funcs = "MAC_TXEN", "GPIO51", "SD1_DATA_0", "PWM5";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad25: PAD_MAC_RXD0_CFG {
+ index = <25>;
+ funcs = "MAC_RXD_0", "GPIO52", "SD1_DATA_1", "PWM6";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad26: PAD_MAC_RXD1_CFG {
+ index = <26>;
+ funcs = "MAC_RXD_1", "GPIO53", "SD1_DATA_2", "PWM7";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad27: PAD_MAC_RXDV_CFG {
+ index = <27>;
+ funcs = "MAC_RXDV", "GPIO54", "SD1_DATA_3", "PWM8";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad28: PAD_MAC_MDC_CFG {
+ index = <28>;
+ funcs = "MAC_MDC", "GPIO55", "", "PWM9";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad29: PAD_MAC_MDIO_CFG {
+ index = <29>;
+ funcs = "MAC_MDIO", "GPIO56";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad30: PAD_SD1_CLK_CFG {
+ index = <30>;
+ funcs = "SD1_CLK", "GPIO57", "I2C1_SCL";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad31: PAD_SD1_CD_CFG {
+ index = <31>;
+ funcs = "SD1_CD", "GPIO58", "I2C1_SDA";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad32: PAD_SD1_CMD_RSP_CFG {
+ index = <32>;
+ funcs = "SD1_CMD_RSP", "GPIO59", "UART1_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad33: PAD_SD1_DATA_0_CFG {
+ index = <33>;
+ funcs = "SD1_DATA_0", "GPIO60", "UART1_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad34: PAD_SD1_DATA_1_CFG {
+ index = <34>;
+ funcs = "SD1_DATA_1", "GPIO61", "UART2_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad35: PAD_SD1_DATA_2_CFG {
+ index = <35>;
+ funcs = "SD1_DATA_2", "GPIO62", "UART2_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad36: PAD_SD1_DATA_3_CFG {
+ index = <36>;
+ funcs = "SD1_DATA_3", "GPIO63";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad37: PAD_GPIO_0_CFG {
+ index = <37>;
+ funcs = "ARM_JTAG_TRSTN", "GPIO0", "AC_I2S_DO", "DW_I2S_DO",
+ "SSI1_CLK", "SSI2_CLK", "ACIP_ADDAT", "PWM6",
+ "TEST_O_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad38: PAD_GPIO_1_CFG {
+ index = <38>;
+ funcs = "ARM_JTAG_TDO", "GPIO1", "AC_I2S_DI", "DW_I2S_DI",
+ "SSI1_CSN_0", "SSI2_CSN_0", "ACIP_DADAT", "PWM7",
+ "TEST_O_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad39: PAD_GPIO_2_CFG {
+ index = <39>;
+ funcs = "ARM_JTAG_TDI", "GPIO2", "AC_I2S_CLK", "DW_I2S_CLK",
+ "SSI1_TXD", "SSI2_TXD", "ACIP_ADBCLK", "PWM8",
+ "TEST_O_INT_SMI_MDIO_O";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad40: PAD_GPIO_3_CFG {
+ index = <40>;
+ funcs = "ARM_JTAG_TCK", "GPIO3", "AC_I2S_WS", "DW_I2S_WS",
+ "SSI1_RXD", "SSI2_RXD", "ACIP_ADLRC", "PWM9",
+ "TEST_I_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad41: PAD_GPIO_4_CFG {
+ index = <41>;
+ funcs = "ARM_JTAG_TMS", "GPIO4", "AC_MCLK", "USB_PWREN",
+ "SD1_CD", "TEST_I_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad42: PAD_SSI0_CLK_CFG {
+ index = <42>;
+ funcs = "SSI0_CLK", "GPIO5", "", "", "SD1_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad43: PAD_SSI0_CSN_0_CFG {
+ index = <43>;
+ funcs = "SSI0_CSN_0", "GPIO6", "", "", "SD1_CMD_RSP";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad44: PAD_SSI0_TXD_CFG {
+ index = <44>;
+ funcs = "SSI0_TXD", "GPIO7", "", "", "SD1_DATA_0";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad45: PAD_SSI0_RXD_CFG {
+ index = <45>;
+ funcs = "SSI0_RXD", "GPIO8", "", "", "SD1_DATA_1";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad46: PAD_SSI0_D2_CFG {
+ index = <46>;
+ funcs = "SSI0_D2", "GPIO9", "UART1_TX", "I2C1_SCL",
+ "SD1_DATA_2";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad47: PAD_SSI0_D3_CFG {
+ index = <47>;
+ funcs = "SSI0_D3", "GPIO10", "UART1_RX", "I2C1_SDA",
+ "SD1_DATA_3";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad48: PAD_SSI1_CLK_CFG {
+ index = <48>;
+ funcs = "SSI1_CLK", "GPIO11", "SSI2_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad49: PAD_SSI1_CSN_0_CFG {
+ index = <49>;
+ funcs = "SSI1_CSN_0", "GPIO14", "SSI2_CSN_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad50: PAD_SSI1_TXD_CFG {
+ index = <50>;
+ funcs = "SSI1_TXD", "GPIO15", "SSI2_TXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad51: PAD_SSI1_RXD_CFG {
+ index = <51>;
+ funcs = "SSI1_RXD", "GPIO16", "SSI2_RXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad52: PAD_SD0_CD_CFG {
+ index = <52>;
+ funcs = "SD0_CD", "GPIO17", "", "ARC_JTAG_TRSTN",
+ "PAE_JTAG_TRSTN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad53: PAD_SD0_CLK_CFG {
+ index = <53>;
+ funcs = "SD0_CLK", "GPIO18", "SSI1_CLK", "ARC_JTAG_TDO",
+ "PAE_JTAG_TDO";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad54: PAD_SD0_CMD_RSP_CFG {
+ index = <54>;
+ funcs = "SD0_CMD_RSP", "GPIO19", "SSI1_TXD", "ARC_JTAG_TDI",
+ "PAE_JTAG_TDI";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad55: PAD_SD0_DATA_0_CFG {
+ index = <55>;
+ funcs = "SD0_DATA_0", "GPIO20", "SSI1_RXD", "ARC_JTAG_TCK",
+ "PAE_JTAG_TCK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad56: PAD_SD0_DATA_1_CFG {
+ index = <56>;
+ funcs = "SD0_DATA_1", "GPIO21", "SSI1_CSN_0", "ARC_JTAG_TMS",
+ "PAE_JTAG_TMS";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad57: PAD_SD0_DATA_2_CFG {
+ index = <57>;
+ funcs = "SD0_DATA_2", "GPIO22", "", "UART2_TX", "I2C2_SCL", "",
+ "ACIP_DABCLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad58: PAD_SD0_DATA_3_CFG {
+ index = <58>;
+ funcs = "SD0_DATA_3", "GPIO23", "SSI1_CSN_0", "UART2_RX",
+ "I2C2_SDA", "", "ACIP_DALRC";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad59: PAD_SADC_XAIN0_CFG {
+ index = <59>;
+ funcs = "SADC_XAIN0", "GPIO26";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad60: PAD_SADC_XAIN1_CFG {
+ index = <60>;
+ funcs = "SADC_XAIN1", "GPIO27";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad61: PAD_SADC_XAIN2_CFG {
+ index = <61>;
+ funcs = "SADC_XAIN2", "GPIO24";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad62: PAD_SADC_XAIN3_CFG {
+ index = <62>;
+ funcs = "SADC_XAIN3", "GPIO25";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad63: PAD_GPIO_28_CFG {
+ index = <63>;
+ funcs = "GPIO28", "", "ETH_LINK_ACT", "PWM10",
+ "USB_DBG_CLK", "SD1_CD", "TEST_O_INT_RMII_TXEN",
+ "MAC_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad64: PAD_GPIO_29_CFG {
+ index = <64>;
+ funcs = "GPIO29", "", "ETH_LINK_STA", "PWM11", "RTC_CLK",
+ "ETH_LINK_SPD", "TEST_O_INT_SMI_MDIO_OE",
+ "MAC_MDIO";
+ pupd = <0>;
+ ds = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/fh8852v210.dts b/arch/arm/boot/dts/fh8852v210.dts
new file mode 100644
index 00000000..703df11e
--- /dev/null
+++ b/arch/arm/boot/dts/fh8852v210.dts
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2017 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+/include/ "fh8852v210_pinctrl.dtsi"
+/ {
+
+
+ model = "FULLHAN FH8852V210";
+ compatible = "fh,fh8852v210";
+ interrupt-parent = <&intc>;
+ aliases {
+ i2c0 = &i2cbus0;
+ i2c1 = &i2cbus1;
+ i2c2 = &i2cbus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ ttyS0 = &serial0;
+ ttyS1 = &serial1;
+ ttyS2 = &serial2;
+ };
+
+ cpus {
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,arm1176jzf-s";
+ };
+ };
+
+ chosen {
+ bootargs = "coherent_pool=2M";
+ };
+
+ intc: interrupt-controller@E0200000 {
+ compatible = "fh,fh-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xE0200000 0x1000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pmu@f0000000 {
+ compatible = "fh,fh-pmu";
+ reg = <0xf0000000 0x2100>;
+ SWRST_MAIN_CTRL = <0x40>;
+ };
+ timer0: timer@f0c00000 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00000 0x14>;
+ };
+
+ timer1: timer@f0c00014 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00014 0x14>;
+ };
+
+ gpio0: gpio@f0300000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf0300000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <26>;
+ id = <0>;
+ ngpio = <32>;
+ base = <0>;
+ };
+
+ gpio1: gpio@f4000000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf4000000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <40>;
+ id = <1>;
+ ngpio = <32>;
+ base = <32>;
+ };
+
+ fhdma0: dma@e0300000 {
+ compatible = "fh,fh-axi-dmac";
+ reg = <0xe0300000 0x1000>;
+ interrupts = <23>;
+ chan_allocation_order = <0>;
+ chan_priority = <1>;
+ block_size = <0x800>;
+ data_width = <2 0 0 0>;
+ clocks = <&ahb_clk>;
+ };
+
+ aes: aes@0xe8200000 {
+ compatible = "fh,fh-aes";
+ reg = <0xe8200000 0x1000>;
+ interrupts = <16>;
+ };
+ rtc: rtc@f1500000 {
+ compatible = "fh,fh_rtc";
+ reg = <0xf1500000 0x1000>;
+ interrupts = <33>;
+ clocks = <&rtc_hclk_gate>;
+ lut_cof = <71>;
+ lut_offset = <0xf6>;
+ tsensor_cp_default_out = <0x9cc>;
+ };
+ sadc: sadc@f1200000 {
+ compatible = "fh,fh-sadc";
+ reg = <0xf1200000 0x1000>;
+ interrupts = <20>;
+ ref-vol = <1800>;
+ active-bit = <0xfff>;
+ };
+ efuse: efuse@0xf1600000 {
+ compatible = "fh,fh-efuse";
+ reg = <0xf1600000 0x1000>;
+ key_switch = "enable";
+ indep_power = "enable";
+ };
+ fh_perf: fh_perf@0xf0002018 {
+ compatible = "fh,fh-perf";
+ reg = <0xf0000000 0x4000>;
+ interrupts = < 5 >;
+
+ };
+ spi_bus0: spi@f0500000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0500000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <6>;
+ cs1_gpio = <55>;
+ dma_enable = "disable";
+ swap_support = "enable";
+ rx_hs_no = <4>;
+ tx_hs_no = <5>;
+ bus_no = <0>;
+ multi_wire_size = <2>;
+ clk_name = "spi0_clk";
+ rx_dma_channel = <0>;
+ tx_dma_channel = <1>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <28>;
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fh,m25p80";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ reg = <0x0 0>; //first value means which slave bind to the master. 0 means chip 0. 1 means chip 1
+ partition@0 {
+ reg = <0x0 0x40000>;
+ label = "bootstrap";
+ };
+ partition@40000 {
+ reg = <0x40000 0x10000>;
+ label = "uboot-env";
+ };
+ partition@50000 {
+ reg = <0x50000 0x30000>;
+ label = "uboot";
+ };
+ partition@80000 {
+ reg = <0x80000 0x400000>;
+ label = "kernel";
+ };
+ partition@480000 {
+ reg = <0x480000 0x80000>;
+ label = "rootfs";
+ };
+ partition@500000 {
+ reg = <0x500000 0x300000>;
+ label = "app";
+ };
+
+ };
+ spidev0: spi@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ spi_bus1: spi@f0600000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0600000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <14>;
+ cs1_gpio = <57>;
+ dma_enable = "disable";
+ swap_support = "disable";
+ rx_hs_no = <2>;
+ tx_hs_no = <3>;
+ bus_no = <1>;
+ clk_name = "spi1_clk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <21>;
+ spidev1: spi@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x0 0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev2: spi@2 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ fhdwi2s: i2s@f0900000 {
+ compatible = "fh,fh-dw_i2s";
+ reg = <0xf0900000 0x1000>;
+ interrupts = <25>;
+ clocks = <&i2s_clk>, <&ac_clk>;
+ clock-names = "i2s_clk", "acodec_mclk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ dma_master = <0>;
+ dma_rx_hs_num = <10>;
+ dma_tx_hs_num = <11>;
+ };
+
+ fhacw: acw@f0a00000 {
+ compatible = "fh,fh-acw";
+ reg = <0xf0a00000 0x1000>;
+ interrupts = <19>;
+ clocks = <&ac_clk>;
+ clock-names = "ac_clk";
+ rx_dma_channel = <4>;
+ tx_dma_channel = <5>;
+ dma_master = <0>;
+ dma_rx_hs_num = <0>;
+ dma_tx_hs_num = <1>;
+ };
+
+ pwm: pwm@f0400000{
+ compatible = "fh,fh-pwm";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <36>;
+ npwm = <14>;
+ };
+ serial0: serial@f0700000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0700000 0x1000>;
+ interrupts = <30>;
+ clock-frequency = <16666667>;
+ fifo-size = <32>;
+ };
+ serial1: serial@f0800000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0800000 0x1000>;
+ interrupts = <31>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ serial2: serial@f1300000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf1300000 0x1000>;
+ interrupts = <41>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ gmac0: gmac@e0600000 {
+ compatible = "fh,fh-gmac";
+ reg = <0xe0600000 0x2000>;
+ interrupts = <44>;
+ phyreset-gpio = <29>;
+ };
+ sdc0: sdc0@e2000000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2000000 0x4000>;
+ interrupts = <42>;
+ id = <0>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <0>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <0>;
+ };
+ sdc1: sdc1@e2200000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2200000 0x4000>;
+ interrupts = <43>;
+ id = <1>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <1>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <2>;
+ };
+ wdt: wdt@f0d00000{
+ compatible = "fh,fh-wdt";
+ reg = <0xf0d00000 0x1000>;
+ interrupts = <2>;
+ mode = <1>;
+ };
+ i2cbus0: i2c@f0200000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0200000 0x2000>;
+ interrupts = <11>;
+ };
+ i2cbus1: i2c@f0b00000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0b00000 0x2000>;
+ interrupts = <12>;
+ };
+ i2cbus2: i2c@0xF0100000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xF0100000 0x2000>;
+ interrupts = <46>;
+ };
+ clocks: src_clk@0xf0000000{
+ compatible = "fh,fh-clk";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf0000000 0x80>;
+ ranges;
+
+ osc_clk: mxtal@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_clk";
+ };
+
+ pll_ddr_rclk: pllddrr{
+ #clock-cells = <0>;
+ compatible = "fh pll-ddr-rclk";
+ reg = <0xf0000010 0x4>,<0xf0000018 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_ddr_rclk";
+ };
+ pll_cpu_pclk: pllcpup{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-pclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_pclk";
+ };
+ pll_cpu_rclk: pllcpur{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-rclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_rclk";
+ };
+ pll_sys_pclk: pllsysp{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-pclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_pclk";
+ };
+ pll_sys_rclk: pllsysr{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-rclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_rclk";
+ };
+ sysp_div12_clk: syspdiv12clk{
+ #clock-cells = <0>;
+ compatible = "fh sysp-div12-clk";
+ reg = <0xf0000038 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sysp_div12_clk";
+ };
+ ddr_clk: ddrclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ddr-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clocks = <&pll_ddr_rclk>;
+ clock-output-names = "ddr_clk";
+ };
+ arm_clk: armclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arm-clk";
+ reg = <0x0 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_pclk>;
+ clock-output-names = "arm_clk";
+ };
+ arc_clk: arcclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arc-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ gate = <0x4000000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_rclk>;
+ clock-output-names = "arc_clk";
+ };
+ ahb_clk: ahbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ahb-clk";
+ reg = <0xf0000024 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ div = <0xf0000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_sys_pclk>;
+ clock-output-names = "ahb_clk";
+ };
+ isp_aclk: ispaclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispa-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00>;
+ gate = <0x1>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "isp_aclk";
+ };
+ ispb_aclk: ispbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispb-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "ispb_aclk";
+ };
+ vpu_clk: vpuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80000000>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "vpu_clk";
+ };
+ pix_clk: pixclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-pix-clk";
+ reg = <0xf000002c 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "pix_clk";
+ };
+ jpeg_clk: jpegclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-clk";
+ reg = <0xf000005c 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "jpeg_clk";
+ };
+ bgm_clk: bgmclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "bgm_clk";
+ };
+ jpeg_adapt_clk: jpegadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-adapt-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2>;
+ clocks = <&jpeg_clk>;
+ clock-output-names = "jpeg_adapt_clk";
+ };
+ spi0_clk: spi0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x80>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi0_clk";
+ };
+ sdc0_clk: sdc0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf00>;
+ gate = <0x200>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc0_clk";
+ };
+ spi2_clk: spi2clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi2-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000>;
+ gate = <0x2>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi2_clk";
+ };
+ spi1_clk: spi1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x100>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi1_clk";
+ };
+ sdc1_clk: sdc1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf000000>;
+ gate = <0x400>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc1_clk";
+ };
+ veu_clk: veuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ div = <0x7000000>;
+ gate = <0x10>;
+ mux = <0x4>;
+ clocks = <&pll_sys_pclk>,<&pll_sys_rclk>;
+ clock-output-names = "veu_clk";
+ };
+ veu_adapt_clk: veuadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-adapt-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clocks = <&veu_clk>;
+ clock-output-names = "veu_adapt_clk";
+ };
+ cis_clk_out: cisclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-cis-clk-out";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x800000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "cis_clk_out";
+ };
+ eth_clk: ethclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-eth-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ gate = <0x2000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "eth_clk";
+ };
+ eth_rmii_clk: ethrmiiclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ethrmii-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "eth_rmii_clk";
+ };
+ i2c0_clk: i2c0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f0000>;
+ gate = <0x1000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c0_clk";
+ };
+
+ i2c1_clk: i2c1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x8000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c1_clk";
+ };
+ i2c2_clk: i2c2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x00000008>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c2_clk";
+ };
+
+ uart0_clk: uart0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f>;
+ gate = <0x2000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart0_clk";
+ };
+
+ uart1_clk: uart1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f00>;
+ gate = <0x4000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart1_clk";
+ };
+ uart2_clk: uart2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f>;
+ gate = <0x8000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart2_clk";
+ };
+ pwm_clk: pwmclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pwm-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x10000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pwm_clk";
+ };
+ efuse_clk: efuseclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-efuse-clk";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x200000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "efuse_clk";
+ };
+ pts_clk: ptsclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pts-clk";
+ reg = <0xf000002c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1ff>;
+ gate = <0x80000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pts_clk";
+ };
+ tmr0_clk: tmr0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-tmr0-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x20000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "tmr0_clk";
+ };
+
+ sadc_clk: sadcclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sadc-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f0000>;
+ gate = <0x4000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "sadc_clk";
+ };
+ gpio0_dbclk: gpio0dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff>;
+ gate = <0x8000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio0_dbclk";
+ };
+ gpio1_dbclk: gpio1dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff0000>;
+ gate = <0x80000000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio1_dbclk";
+ };
+ wdt_clk: wdtclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-wdt-clk";
+ reg = <0xf0000038 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xff00>;
+ gate = <0x8000000>;
+ clocks = <&ahb_clk>;
+ clock-output-names = "wdt_clk";
+ };
+ ac_clk: acclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ac-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f>;
+ gate = <0x800>;
+ clocks = <&osc_clk>;
+ clock-output-names = "ac_clk";
+ };
+ i2s_clk: i2sclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-i2s-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x1000000>;
+ clocks = <&ac_clk>;
+ clock-output-names = "i2s_clk";
+ };
+ mipi_dphy_clk: mipidphyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-dphy-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x100000>;
+ clock-output-names = "mipi_dphy_clk";
+ };
+ mipi_wrap_gate: mipiwrapclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-wrap-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "mipi_wrap_gate";
+ };
+ rtc_hclk_gate: rtchclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-rtc-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "rtc_hclk_gate";
+ };
+ emac_hclk_gate: emachclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-emac-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "emac_hclk_gate";
+ };
+ usb_clk: usbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-usb-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "usb_clk";
+ };
+ aes_hclk_gate: aeshclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-aes-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80>;
+ clock-output-names = "aes_hclk_gate";
+ };
+ ephy_clk_gate: ephyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ephy-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1>;
+ clock-output-names = "ephy_clk_gate";
+ };
+ sdc0_clk8x_gate: sdc08xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc08x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clock-output-names = "sdc0_clk8x_gate";
+ };
+ sdc1_clk8x_gate: sdc18xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc18x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x8>;
+ clock-output-names = "sdc1_clk8x_gate";
+ };
+ mipic_pclk_gate: mipicpclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipic-pclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10>;
+ clock-output-names = "mipic_pclk_gate";
+ };
+ gpio0_pclk_gate: gpio0pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x4000>;
+ clock-output-names = "gpio0_pclk_gate";
+ };
+ gpio1_pclk_gate: gpio1pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "gpio1_pclk_gate";
+ };
+ isp_hclk_gate: isphclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-isp-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "isp_hclk_gate";
+ };
+ veu_hclk_gate: veuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "veu_hclk_gate";
+ };
+ bgm_hclk_gate: bgmhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clock-output-names = "bgm_hclk_gate";
+ };
+ adapt_hclk_gate: adapthclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-adapt-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x8000000>;
+ clock-output-names = "adapt_hclk_gate";
+ };
+ jpg_hclk_gate: jpghclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "jpg_hclk_gate";
+ };
+ jpg_adapt_gate: jpgadaptclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-adapt-clk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "jpg_adapt_gate";
+ };
+ vpu_hclk_gate: vpuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "vpu_hclk_gate";
+ };
+ sdc0_clk_sample: sdc0clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf0000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_sample";
+ };
+ sdc0_clk_drv: sdc0clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_drv";
+ };
+
+ sdc1_clk_sample: sdc1clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_sample";
+ };
+
+ sdc1_clk_drv: sdc1clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf000>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_drv";
+ };
+ };
+ };
+
+ usb_otg@e0700000 {
+ compatible = "fh_usb";
+ reg = <0xe0700000 100000>;
+ interrupts = <39>;
+ clocks = <&usb_clk>;
+ dr_mode = "host";
+ vbus_pwren = <47>;
+ clock-names = "otg";
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
+ };
+
+ usb2_phy: usbphy {
+ compatible = "fh,fh-usb2-phy";
+ #phy-cells = <0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/fh8852v210_pinctrl.dtsi b/arch/arm/boot/dts/fh8852v210_pinctrl.dtsi
new file mode 100644
index 00000000..cc0129ca
--- /dev/null
+++ b/arch/arm/boot/dts/fh8852v210_pinctrl.dtsi
@@ -0,0 +1,2386 @@
+/*
+ * Copyright (C) 2020 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ #define PUPD_NONE (0)
+ #define PUPD_UP (1)
+ #define PUPD_DOWN (2)
+*/
+
+/ {
+ pinctrl: pinctrl@f0000080 {
+ compatible = "fh,fh-pinctrl";
+ reg = <0xf0000080 0x104>;
+ pad-num = <65>;
+ max-mux = <9>;
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_ETH
+ &pinctrl_I2C0
+ &pinctrl_PWM2
+ &pinctrl_PWM3
+ &pinctrl_PWM4
+ &pinctrl_PWM5
+ &pinctrl_PWM6
+ &pinctrl_PWM7
+ &pinctrl_PWM8
+ &pinctrl_PWM9
+ &pinctrl_SADC_XAIN0
+ &pinctrl_SADC_XAIN1
+ &pinctrl_SD0_NO_WP
+ &pinctrl_SENSOR_CLK
+ &pinctrl_SSI0_4BIT
+ &pinctrl_UART0
+ &pinctrl_UART1
+ &pinctrl_GPIO4
+ &pinctrl_GPIO13
+ &pinctrl_GPIO30
+ &pinctrl_GPIO31
+ &pinctrl_GPIO32
+ &pinctrl_GPIO43
+ &pinctrl_GPIO44
+ &pinctrl_GPIO47
+
+ &pinctrl_GPIO11
+ &pinctrl_GPIO14
+ &pinctrl_GPIO15
+ &pinctrl_GPIO16
+ &pinctrl_GPIO24
+ &pinctrl_GPIO25
+ &pinctrl_GPIO45
+ &pinctrl_GPIO46
+ &pinctrl_GPIO48
+ &pinctrl_GPIO49
+ &pinctrl_GPIO50
+ &pinctrl_GPIO51
+ &pinctrl_GPIO52
+ &pinctrl_GPIO53
+ &pinctrl_GPIO54
+ &pinctrl_GPIO55
+ &pinctrl_GPIO56
+ &pinctrl_GPIO57
+ &pinctrl_GPIO58
+ &pinctrl_GPIO59
+ &pinctrl_GPIO60
+ &pinctrl_GPIO61
+ &pinctrl_GPIO62
+ &pinctrl_GPIO63
+ >;
+ pinctrl_groups {
+ pinctrl_ACI2S: ACI2S {
+ fh,pins = <
+ &mux_AC_I2S_CLK 0
+ &mux_AC_I2S_DI 0
+ &mux_AC_I2S_DO 0
+ &mux_AC_I2S_WS 0
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_AC_MCLK: AC_MCLK {
+ fh,pins = <
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_ARCJTAG: ARCJTAG {
+ fh,pins = <
+ &mux_ARC_JTAG_TCK 0
+ &mux_ARC_JTAG_TDI 0
+ &mux_ARC_JTAG_TDO 0
+ &mux_ARC_JTAG_TMS 0
+ &mux_ARC_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_ARMJTAG: ARMJTAG {
+ fh,pins = <
+ &mux_ARM_JTAG_TCK 0
+ &mux_ARM_JTAG_TDI 0
+ &mux_ARM_JTAG_TDO 0
+ &mux_ARM_JTAG_TMS 0
+ &mux_ARM_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_DWI2S: DWI2S {
+ fh,pins = <
+ &mux_DW_I2S_CLK 0
+ &mux_DW_I2S_DI 0
+ &mux_DW_I2S_DO 0
+ &mux_DW_I2S_WS 0
+ >;
+ };
+ pinctrl_ETH: ETH {
+ fh,pins = <
+ &mux_ETH_LINK_ACT 1
+ &mux_ETH_LINK_STA 1
+ >;
+ };
+ pinctrl_I2C0: I2C0 {
+ fh,pins = <
+ &mux_I2C0_SCL 0
+ &mux_I2C0_SDA 0
+ >;
+ };
+ pinctrl_I2C1: I2C1 {
+ fh,pins = <
+ &mux_I2C1_SCL 2
+ &mux_I2C1_SDA 2
+ >;
+ };
+ pinctrl_I2C2: I2C2 {
+ fh,pins = <
+ &mux_I2C2_SCL 1
+ &mux_I2C2_SDA 1
+ >;
+ };
+ pinctrl_PAEJTAG: PAEJTAG {
+ fh,pins = <
+ &mux_PAE_JTAG_TCK 0
+ &mux_PAE_JTAG_TDI 0
+ &mux_PAE_JTAG_TDO 0
+ &mux_PAE_JTAG_TMS 0
+ &mux_PAE_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_PWM0: PWM0 {
+ fh,pins = <
+ &mux_PWM0 0
+ >;
+ };
+ pinctrl_PWM1: PWM1 {
+ fh,pins = <
+ &mux_PWM1 0
+ >;
+ };
+ pinctrl_PWM10: PWM10 {
+ fh,pins = <
+ &mux_PWM10 0
+ >;
+ };
+ pinctrl_PWM11: PWM11 {
+ fh,pins = <
+ &mux_PWM11 0
+ >;
+ };
+ pinctrl_PWM2: PWM2 {
+ fh,pins = <
+ &mux_PWM2 0
+ >;
+ };
+ pinctrl_PWM3: PWM3 {
+ fh,pins = <
+ &mux_PWM3 0
+ >;
+ };
+ pinctrl_PWM4: PWM4 {
+ fh,pins = <
+ &mux_PWM4 0
+ >;
+ };
+ pinctrl_PWM5: PWM5 {
+ fh,pins = <
+ &mux_PWM5 0
+ >;
+ };
+ pinctrl_PWM6: PWM6 {
+ fh,pins = <
+ &mux_PWM6 1
+ >;
+ };
+ pinctrl_PWM7: PWM7 {
+ fh,pins = <
+ &mux_PWM7 1
+ >;
+ };
+ pinctrl_PWM8: PWM8 {
+ fh,pins = <
+ &mux_PWM8 1
+ >;
+ };
+ pinctrl_PWM9: PWM9 {
+ fh,pins = <
+ &mux_PWM9 1
+ >;
+ };
+ pinctrl_RMII: RMII {
+ fh,pins = <
+ &mux_MAC_MDC 1
+ &mux_MAC_MDIO 1
+ &mux_MAC_REF_CLK 0
+ &mux_MAC_RMII_CLK 0
+ &mux_MAC_RXDV 0
+ &mux_MAC_RXD_0 0
+ &mux_MAC_RXD_1 0
+ &mux_MAC_TXD_0 0
+ &mux_MAC_TXD_1 0
+ &mux_MAC_TXEN 0
+ >;
+ };
+ pinctrl_RTC: RTC {
+ fh,pins = <
+ &mux_RTC_CLK 0
+ >;
+ };
+ pinctrl_SADC_XAIN0: SADC_XAIN0 {
+ fh,pins = <
+ &mux_SADC_XAIN0 0
+ >;
+ };
+ pinctrl_SADC_XAIN1: SADC_XAIN1 {
+ fh,pins = <
+ &mux_SADC_XAIN1 0
+ >;
+ };
+ pinctrl_SADC_XAIN2: SADC_XAIN2 {
+ fh,pins = <
+ &mux_SADC_XAIN2 0
+ >;
+ };
+ pinctrl_SADC_XAIN3: SADC_XAIN3 {
+ fh,pins = <
+ &mux_SADC_XAIN3 0
+ >;
+ };
+ pinctrl_SD0: SD0 {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_1BIT_NO_WP: SD0_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ >;
+ };
+ pinctrl_SD0_NO_WP: SD0_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_WIFI: SD0_WIFI {
+ fh,pins = <
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD1: SD1 {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_1BIT_NO_WP: SD1_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ >;
+ };
+ pinctrl_SD1_NO_WP: SD1_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_WIFI: SD1_WIFI {
+ fh,pins = <
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SENSOR_CLK: SENSOR_CLK {
+ fh,pins = <
+ &mux_SENSOR_CLK 0
+ >;
+ };
+ pinctrl_SSI0: SSI0 {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI0_4BIT: SSI0_4BIT {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_D2 0
+ &mux_SSI0_D3 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI1: SSI1 {
+ fh,pins = <
+ &mux_GPIO14 0
+ &mux_SSI1_CLK 2
+ &mux_SSI1_RXD 2
+ &mux_SSI1_TXD 2
+ >;
+ };
+ pinctrl_SSI2: SSI2 {
+ fh,pins = <
+ &mux_SSI2_CLK 1
+ &mux_SSI2_CSN_0 1
+ &mux_SSI2_RXD 1
+ &mux_SSI2_TXD 1
+ >;
+ };
+ pinctrl_UART0: UART0 {
+ fh,pins = <
+ &mux_UART0_RX 0
+ &mux_UART0_TX 0
+ >;
+ };
+ pinctrl_UART1: UART1 {
+ fh,pins = <
+ &mux_UART1_RX 0
+ &mux_UART1_TX 0
+ >;
+ };
+ pinctrl_UART2: UART2 {
+ fh,pins = <
+ &mux_UART2_RX 0
+ &mux_UART2_TX 0
+ >;
+ };
+ pinctrl_USB: USB {
+ fh,pins = <
+ &mux_USB_PWREN 0
+ >;
+ };
+ pinctrl_GPIO0: GPIO0 {
+ fh,pins = <
+ &mux_GPIO0 0
+ >;
+ };
+ pinctrl_GPIO1: GPIO1 {
+ fh,pins = <
+ &mux_GPIO1 0
+ >;
+ };
+ pinctrl_GPIO2: GPIO2 {
+ fh,pins = <
+ &mux_GPIO2 0
+ >;
+ };
+ pinctrl_GPIO3: GPIO3 {
+ fh,pins = <
+ &mux_GPIO3 0
+ >;
+ };
+ pinctrl_GPIO4: GPIO4 {
+ fh,pins = <
+ &mux_GPIO4 0
+ >;
+ };
+ pinctrl_GPIO5: GPIO5 {
+ fh,pins = <
+ &mux_GPIO5 0
+ >;
+ };
+ pinctrl_GPIO6: GPIO6 {
+ fh,pins = <
+ &mux_GPIO6 0
+ >;
+ };
+ pinctrl_GPIO7: GPIO7 {
+ fh,pins = <
+ &mux_GPIO7 0
+ >;
+ };
+ pinctrl_GPIO8: GPIO8 {
+ fh,pins = <
+ &mux_GPIO8 0
+ >;
+ };
+ pinctrl_GPIO9: GPIO9 {
+ fh,pins = <
+ &mux_GPIO9 0
+ >;
+ };
+ pinctrl_GPIO10: GPIO10 {
+ fh,pins = <
+ &mux_GPIO10 0
+ >;
+ };
+ pinctrl_GPIO11: GPIO11 {
+ fh,pins = <
+ &mux_GPIO11 0
+ >;
+ };
+ pinctrl_GPIO12: GPIO12 {
+ fh,pins = <
+ &mux_GPIO12 0
+ >;
+ };
+ pinctrl_GPIO13: GPIO13 {
+ fh,pins = <
+ &mux_GPIO13 0
+ >;
+ };
+ pinctrl_GPIO14: GPIO14 {
+ fh,pins = <
+ &mux_GPIO14 0
+ >;
+ };
+ pinctrl_GPIO15: GPIO15 {
+ fh,pins = <
+ &mux_GPIO15 0
+ >;
+ };
+ pinctrl_GPIO16: GPIO16 {
+ fh,pins = <
+ &mux_GPIO16 0
+ >;
+ };
+ pinctrl_GPIO17: GPIO17 {
+ fh,pins = <
+ &mux_GPIO17 0
+ >;
+ };
+ pinctrl_GPIO18: GPIO18 {
+ fh,pins = <
+ &mux_GPIO18 0
+ >;
+ };
+ pinctrl_GPIO19: GPIO19 {
+ fh,pins = <
+ &mux_GPIO19 0
+ >;
+ };
+ pinctrl_GPIO20: GPIO20 {
+ fh,pins = <
+ &mux_GPIO20 0
+ >;
+ };
+ pinctrl_GPIO21: GPIO21 {
+ fh,pins = <
+ &mux_GPIO21 0
+ >;
+ };
+ pinctrl_GPIO22: GPIO22 {
+ fh,pins = <
+ &mux_GPIO22 0
+ >;
+ };
+ pinctrl_GPIO23: GPIO23 {
+ fh,pins = <
+ &mux_GPIO23 0
+ >;
+ };
+ pinctrl_GPIO24: GPIO24 {
+ fh,pins = <
+ &mux_GPIO24 0
+ >;
+ };
+ pinctrl_GPIO25: GPIO25 {
+ fh,pins = <
+ &mux_GPIO25 0
+ >;
+ };
+ pinctrl_GPIO26: GPIO26 {
+ fh,pins = <
+ &mux_GPIO26 0
+ >;
+ };
+ pinctrl_GPIO27: GPIO27 {
+ fh,pins = <
+ &mux_GPIO27 0
+ >;
+ };
+ pinctrl_GPIO28: GPIO28 {
+ fh,pins = <
+ &mux_GPIO28 0
+ >;
+ };
+ pinctrl_GPIO29: GPIO29 {
+ fh,pins = <
+ &mux_GPIO29 0
+ >;
+ };
+ pinctrl_GPIO30: GPIO30 {
+ fh,pins = <
+ &mux_GPIO30 0
+ >;
+ };
+ pinctrl_GPIO31: GPIO31 {
+ fh,pins = <
+ &mux_GPIO31 0
+ >;
+ };
+ pinctrl_GPIO32: GPIO32 {
+ fh,pins = <
+ &mux_GPIO32 0
+ >;
+ };
+ pinctrl_GPIO33: GPIO33 {
+ fh,pins = <
+ &mux_GPIO33 0
+ >;
+ };
+ pinctrl_GPIO34: GPIO34 {
+ fh,pins = <
+ &mux_GPIO34 0
+ >;
+ };
+ pinctrl_GPIO35: GPIO35 {
+ fh,pins = <
+ &mux_GPIO35 0
+ >;
+ };
+ pinctrl_GPIO36: GPIO36 {
+ fh,pins = <
+ &mux_GPIO36 0
+ >;
+ };
+ pinctrl_GPIO37: GPIO37 {
+ fh,pins = <
+ &mux_GPIO37 0
+ >;
+ };
+ pinctrl_GPIO38: GPIO38 {
+ fh,pins = <
+ &mux_GPIO38 0
+ >;
+ };
+ pinctrl_GPIO39: GPIO39 {
+ fh,pins = <
+ &mux_GPIO39 0
+ >;
+ };
+ pinctrl_GPIO40: GPIO40 {
+ fh,pins = <
+ &mux_GPIO40 0
+ >;
+ };
+ pinctrl_GPIO41: GPIO41 {
+ fh,pins = <
+ &mux_GPIO41 0
+ >;
+ };
+ pinctrl_GPIO42: GPIO42 {
+ fh,pins = <
+ &mux_GPIO42 0
+ >;
+ };
+ pinctrl_GPIO43: GPIO43 {
+ fh,pins = <
+ &mux_GPIO43 0
+ >;
+ };
+ pinctrl_GPIO44: GPIO44 {
+ fh,pins = <
+ &mux_GPIO44 0
+ >;
+ };
+ pinctrl_GPIO45: GPIO45 {
+ fh,pins = <
+ &mux_GPIO45 0
+ >;
+ };
+ pinctrl_GPIO46: GPIO46 {
+ fh,pins = <
+ &mux_GPIO46 0
+ >;
+ };
+ pinctrl_GPIO47: GPIO47 {
+ fh,pins = <
+ &mux_GPIO47 0
+ >;
+ };
+ pinctrl_GPIO48: GPIO48 {
+ fh,pins = <
+ &mux_GPIO48 0
+ >;
+ };
+ pinctrl_GPIO49: GPIO49 {
+ fh,pins = <
+ &mux_GPIO49 0
+ >;
+ };
+ pinctrl_GPIO50: GPIO50 {
+ fh,pins = <
+ &mux_GPIO50 0
+ >;
+ };
+ pinctrl_GPIO51: GPIO51 {
+ fh,pins = <
+ &mux_GPIO51 0
+ >;
+ };
+ pinctrl_GPIO52: GPIO52 {
+ fh,pins = <
+ &mux_GPIO52 0
+ >;
+ };
+ pinctrl_GPIO53: GPIO53 {
+ fh,pins = <
+ &mux_GPIO53 0
+ >;
+ };
+ pinctrl_GPIO54: GPIO54 {
+ fh,pins = <
+ &mux_GPIO54 0
+ >;
+ };
+ pinctrl_GPIO55: GPIO55 {
+ fh,pins = <
+ &mux_GPIO55 0
+ >;
+ };
+ pinctrl_GPIO56: GPIO56 {
+ fh,pins = <
+ &mux_GPIO56 0
+ >;
+ };
+ pinctrl_GPIO57: GPIO57 {
+ fh,pins = <
+ &mux_GPIO57 0
+ >;
+ };
+ pinctrl_GPIO58: GPIO58 {
+ fh,pins = <
+ &mux_GPIO58 0
+ >;
+ };
+ pinctrl_GPIO59: GPIO59 {
+ fh,pins = <
+ &mux_GPIO59 0
+ >;
+ };
+ pinctrl_GPIO60: GPIO60 {
+ fh,pins = <
+ &mux_GPIO60 0
+ >;
+ };
+ pinctrl_GPIO61: GPIO61 {
+ fh,pins = <
+ &mux_GPIO61 0
+ >;
+ };
+ pinctrl_GPIO62: GPIO62 {
+ fh,pins = <
+ &mux_GPIO62 0
+ >;
+ };
+ pinctrl_GPIO63: GPIO63 {
+ fh,pins = <
+ &mux_GPIO63 0
+ >;
+ };
+ pinctrl_SD1_EMMC: SD1_EMMC {
+ fh,pins = <
+ &mux_SD1_CD 3
+ &mux_SD1_CLK 3
+ &mux_SD1_CMD_RSP 3
+ &mux_SD1_DATA_0 3
+ &mux_SD1_DATA_1 3
+ &mux_SD1_DATA_2 3
+ &mux_SD1_DATA_3 3
+ >;
+ };
+ };
+ pinmux: pinmux {
+ compatible = "fh,fh-pinmux";
+ #list-cells = <1>;
+ mux_AC_I2S_CLK: AC_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_AC_I2S_DI: AC_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_AC_I2S_DO: AC_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_AC_I2S_WS: AC_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_AC_MCLK: AC_MCLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+
+ mux_ARC_JTAG_TCK: ARC_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_ARC_JTAG_TDI: ARC_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_ARC_JTAG_TDO: ARC_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_ARC_JTAG_TMS: ARC_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_ARC_JTAG_TRSTN: ARC_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_ARM_JTAG_TCK: ARM_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_ARM_JTAG_TDI: ARM_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_ARM_JTAG_TDO: ARM_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_ARM_JTAG_TMS: ARM_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_ARM_JTAG_TRSTN: ARM_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+
+ mux_DW_I2S_CLK: DW_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_DW_I2S_DI: DW_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_DW_I2S_DO: DW_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_DW_I2S_WS: DW_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+
+ mux_ETH_LINK_ACT: ETH_LINK_ACT {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad1
+ &pad63
+ >;
+ };
+ mux_ETH_LINK_SPD: ETH_LINK_SPD {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+ mux_ETH_LINK_STA: ETH_LINK_STA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+
+ mux_I2C0_SCL: I2C0_SCL {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_I2C0_SDA: I2C0_SDA {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+
+ mux_I2C1_SCL: I2C1_SCL {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad11
+ &pad30
+ &pad46
+ >;
+ };
+ mux_I2C1_SDA: I2C1_SDA {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad12
+ &pad31
+ &pad47
+ >;
+ };
+
+ mux_I2C2_SCL: I2C2_SCL {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad16
+ &pad57
+ >;
+ };
+ mux_I2C2_SDA: I2C2_SDA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad17
+ &pad58
+ >;
+ };
+
+ mux_MAC_MDC: MAC_MDC {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad28
+ &pad63
+ >;
+ };
+ mux_MAC_MDIO: MAC_MDIO {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad29
+ &pad64
+ >;
+ };
+ mux_MAC_REF_CLK: MAC_REF_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad21
+ >;
+ };
+ mux_MAC_RMII_CLK: MAC_RMII_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_MAC_RXDV: MAC_RXDV {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_MAC_RXD_0: MAC_RXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_MAC_RXD_1: MAC_RXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_MAC_TXD_0: MAC_TXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_MAC_TXD_1: MAC_TXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_MAC_TXEN: MAC_TXEN {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+
+ mux_PAE_JTAG_TCK: PAE_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_PAE_JTAG_TDI: PAE_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_PAE_JTAG_TDO: PAE_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_PAE_JTAG_TMS: PAE_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_PAE_JTAG_TRSTN: PAE_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_PWM0: PWM0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_PWM1: PWM1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_PWM10: PWM10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_PWM11: PWM11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_PWM2: PWM2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ &pad18
+ &pad20
+ >;
+ };
+ mux_PWM3: PWM3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ &pad19
+ &pad22
+ >;
+ };
+ mux_PWM4: PWM4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad23
+ >;
+ };
+ mux_PWM5: PWM5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad24
+ >;
+ };
+ mux_PWM6: PWM6 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad25
+ &pad37
+ >;
+ };
+ mux_PWM7: PWM7 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad26
+ &pad38
+ >;
+ };
+ mux_PWM8: PWM8 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad27
+ &pad39
+ >;
+ };
+ mux_PWM9: PWM9 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad28
+ &pad40
+ >;
+ };
+
+ mux_RTC_CLK: RTC_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+
+ mux_SADC_XAIN0: SADC_XAIN0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_SADC_XAIN1: SADC_XAIN1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_SADC_XAIN2: SADC_XAIN2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_SADC_XAIN3: SADC_XAIN3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+
+ mux_SD0_CD: SD0_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_SD0_CLK: SD0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <3>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_SD0_CMD_RSP: SD0_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_SD0_DATA_0: SD0_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_SD0_DATA_1: SD0_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_SD0_DATA_2: SD0_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_SD0_DATA_3: SD0_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+
+ mux_SD1_CD: SD1_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad10
+ &pad22
+ &pad31
+ &pad41
+ &pad63
+ >;
+ };
+ mux_SD1_CLK: SD1_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <3>;
+ fh,pads = <
+ &pad9
+ &pad20
+ &pad30
+ &pad42
+ >;
+ };
+ mux_SD1_CMD_RSP: SD1_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad23
+ &pad32
+ &pad43
+ >;
+ };
+ mux_SD1_DATA_0: SD1_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad12
+ &pad24
+ &pad33
+ &pad44
+ >;
+ };
+ mux_SD1_DATA_1: SD1_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad25
+ &pad34
+ &pad45
+ >;
+ };
+ mux_SD1_DATA_2: SD1_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad26
+ &pad35
+ &pad46
+ >;
+ };
+ mux_SD1_DATA_3: SD1_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad15
+ &pad27
+ &pad36
+ &pad47
+ >;
+ };
+
+ mux_SENSOR_CLK: SENSOR_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+
+ mux_SSI0_CLK: SSI0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_SSI0_D2: SSI0_D2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_SSI0_D3: SSI0_D3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_SSI0_RXD: SSI0_RXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_SSI0_TXD: SSI0_TXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+
+ mux_SSI1_CLK: SSI1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad37
+ &pad48
+ &pad53
+ >;
+ };
+ mux_SSI1_RXD: SSI1_RXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad40
+ &pad51
+ &pad55
+ >;
+ };
+ mux_SSI1_TXD: SSI1_TXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad39
+ &pad50
+ &pad54
+ >;
+ };
+
+ mux_SSI2_CLK: SSI2_CLK {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad37
+ &pad48
+ >;
+ };
+ mux_SSI2_CSN_0: SSI2_CSN_0 {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad38
+ &pad49
+ >;
+ };
+ mux_SSI2_RXD: SSI2_RXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad40
+ &pad51
+ >;
+ };
+ mux_SSI2_TXD: SSI2_TXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad39
+ &pad50
+ >;
+ };
+
+ mux_UART0_RX: UART0_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_UART0_TX: UART0_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+
+ mux_UART1_RX: UART1_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ &pad33
+ &pad47
+ >;
+ };
+ mux_UART1_TX: UART1_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ &pad32
+ &pad46
+ >;
+ };
+
+ mux_UART2_RX: UART2_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad17
+ &pad35
+ &pad58
+ >;
+ };
+ mux_UART2_TX: UART2_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad16
+ &pad34
+ &pad57
+ >;
+ };
+
+ mux_USB_PWREN: USB_PWREN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ &pad41
+ >;
+ };
+
+ mux_GPIO0: GPIO0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_GPIO1: GPIO1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_GPIO2: GPIO2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_GPIO3: GPIO3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_GPIO4: GPIO4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_GPIO5: GPIO5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_GPIO6: GPIO6 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad43
+ >;
+ };
+ mux_GPIO7: GPIO7 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+ mux_GPIO8: GPIO8 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_GPIO9: GPIO9 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_GPIO10: GPIO10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_GPIO11: GPIO11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad48
+ >;
+ };
+ mux_GPIO12: GPIO12 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+ mux_GPIO13: GPIO13 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad8
+ >;
+ };
+ mux_GPIO14: GPIO14 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad49
+ >;
+ };
+ mux_GPIO15: GPIO15 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad50
+ >;
+ };
+ mux_GPIO16: GPIO16 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad51
+ >;
+ };
+ mux_GPIO17: GPIO17 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_GPIO18: GPIO18 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_GPIO19: GPIO19 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_GPIO20: GPIO20 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_GPIO21: GPIO21 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_GPIO22: GPIO22 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_GPIO23: GPIO23 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+ mux_GPIO24: GPIO24 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_GPIO25: GPIO25 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+ mux_GPIO26: GPIO26 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_GPIO27: GPIO27 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_GPIO28: GPIO28 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_GPIO29: GPIO29 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_GPIO30: GPIO30 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad0
+ >;
+ };
+ mux_GPIO31: GPIO31 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad1
+ >;
+ };
+ mux_GPIO32: GPIO32 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad2
+ >;
+ };
+ mux_GPIO33: GPIO33 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+ mux_GPIO34: GPIO34 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_GPIO35: GPIO35 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_GPIO36: GPIO36 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+ mux_GPIO37: GPIO37 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ >;
+ };
+ mux_GPIO38: GPIO38 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ >;
+ };
+ mux_GPIO39: GPIO39 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ >;
+ };
+ mux_GPIO40: GPIO40 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ >;
+ };
+ mux_GPIO41: GPIO41 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ >;
+ };
+ mux_GPIO42: GPIO42 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ >;
+ };
+ mux_GPIO43: GPIO43 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_GPIO44: GPIO44 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_GPIO45: GPIO45 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad18
+ >;
+ };
+ mux_GPIO46: GPIO46 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad19
+ >;
+ };
+ mux_GPIO47: GPIO47 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ >;
+ };
+ mux_GPIO48: GPIO48 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_GPIO49: GPIO49 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_GPIO50: GPIO50 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_GPIO51: GPIO51 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+ mux_GPIO52: GPIO52 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_GPIO53: GPIO53 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_GPIO54: GPIO54 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_GPIO55: GPIO55 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad28
+ >;
+ };
+ mux_GPIO56: GPIO56 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad29
+ >;
+ };
+ mux_GPIO57: GPIO57 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad30
+ >;
+ };
+ mux_GPIO58: GPIO58 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad31
+ >;
+ };
+ mux_GPIO59: GPIO59 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad32
+ >;
+ };
+ mux_GPIO60: GPIO60 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad33
+ >;
+ };
+ mux_GPIO61: GPIO61 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad34
+ >;
+ };
+ mux_GPIO62: GPIO62 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad35
+ >;
+ };
+ mux_GPIO63: GPIO63 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad36
+ >;
+ };
+ };
+ pinpad: pinpad {
+ compatible = "fh,fh-pinpad";
+ pad0: PAD_BOOT_MODE_CFG {
+ index = <0>;
+ funcs = "GPIO30";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad1: PAD_BOOT_SEL1_CFG {
+ index = <1>;
+ funcs = "GPIO31", "ETH_LINK_ACT";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad2: PAD_BOOT_SEL0_CFG {
+ index = <2>;
+ funcs = "GPIO32", "ETH_LINK_STA", "ETH_LINK_SPD";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad3: PAD_UART0_TX_CFG {
+ index = <3>;
+ funcs = "UART0_TX", "GPIO33";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad4: PAD_UART0_RX_CFG {
+ index = <4>;
+ funcs = "UART0_RX", "GPIO34";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad5: PAD_I2C0_SCL_CFG {
+ index = <5>;
+ funcs = "I2C0_SCL", "GPIO35";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad6: PAD_I2C0_SDA_CFG {
+ index = <6>;
+ funcs = "I2C0_SDA", "GPIO36";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad7: PAD_SENSOR_CLK_CFG {
+ index = <7>;
+ funcs = "SENSOR_CLK", "GPIO12";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad8: PAD_SENSOR_RSTN_CFG {
+ index = <8>;
+ funcs = "GPIO13";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad9: PAD_UART1_TX_CFG {
+ index = <9>;
+ funcs = "UART1_TX", "GPIO39", "", "SD1_CLK", "", "",
+ "TEST_O_INT_RMII_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad10: PAD_UART1_RX_CFG {
+ index = <10>;
+ funcs = "UART1_RX", "GPIO40", "", "SD1_CD", "", "",
+ "TEST_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad11: PAD_I2C1_SCL_CFG {
+ index = <11>;
+ funcs = "I2C1_SCL", "GPIO37", "PWM2", "SD1_CMD_RSP", "",
+ "SSI1_CLK", "TEST_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad12: PAD_I2C1_SDA_CFG {
+ index = <12>;
+ funcs = "I2C1_SDA", "GPIO38", "PWM3", "SD1_DATA_0", "",
+ "SSI1_CSN_0", "TEST_INT_RMII_TXEN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad13: PAD_UART2_TX_CFG {
+ index = <13>;
+ funcs = "UART2_TX", "GPIO41", "PWM4", "SD1_DATA_1", "",
+ "SSI1_TXD", "TEST_O_INT_RMII_RXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad14: PAD_UART2_RX_CFG {
+ index = <14>;
+ funcs = "UART2_RX", "GPIO42", "PWM5", "SD1_DATA_2", "",
+ "SSI1_RXD", "TEST_O_INT_RMII_RXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad15: PAD_USB_PWREN_CFG {
+ index = <15>;
+ funcs = "USB_PWREN", "GPIO47", "", "SD1_DATA_3", "", "",
+ "TEST_O_INT_RMII_CRSDV";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad16: PAD_PWM0_CFG {
+ index = <16>;
+ funcs = "PWM0", "GPIO43", "I2C2_SCL", "UART2_TX", "", "",
+ "TEST_O_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad17: PAD_PWM1_CFG {
+ index = <17>;
+ funcs = "PWM1", "GPIO44", "I2C2_SDA", "UART2_RX", "", "",
+ "TEST_O_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad18: PAD_PWM2_CFG {
+ index = <18>;
+ funcs = "PWM2", "GPIO45";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad19: PAD_PWM3_CFG {
+ index = <19>;
+ funcs = "PWM3", "GPIO46";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad20: PAD_MAC_RMII_CLK_CFG {
+ index = <20>;
+ funcs = "MAC_RMII_CLK", "GPIO48", "SD1_CLK", "PWM2";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad21: PAD_MAC_REF_CLK_CFG {
+ index = <21>;
+ funcs = "MAC_REF_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad22: PAD_MAC_TXD0_CFG {
+ index = <22>;
+ funcs = "MAC_TXD_0", "GPIO49", "SD1_CD", "PWM3";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad23: PAD_MAC_TXD1_CFG {
+ index = <23>;
+ funcs = "MAC_TXD_1", "GPIO50", "SD1_CMD_RSP", "PWM4";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad24: PAD_MAC_TXEN_CFG {
+ index = <24>;
+ funcs = "MAC_TXEN", "GPIO51", "SD1_DATA_0", "PWM5";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad25: PAD_MAC_RXD0_CFG {
+ index = <25>;
+ funcs = "MAC_RXD_0", "GPIO52", "SD1_DATA_1", "PWM6";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad26: PAD_MAC_RXD1_CFG {
+ index = <26>;
+ funcs = "MAC_RXD_1", "GPIO53", "SD1_DATA_2", "PWM7";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad27: PAD_MAC_RXDV_CFG {
+ index = <27>;
+ funcs = "MAC_RXDV", "GPIO54", "SD1_DATA_3", "PWM8";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad28: PAD_MAC_MDC_CFG {
+ index = <28>;
+ funcs = "MAC_MDC", "GPIO55", "", "PWM9";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad29: PAD_MAC_MDIO_CFG {
+ index = <29>;
+ funcs = "MAC_MDIO", "GPIO56";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad30: PAD_SD1_CLK_CFG {
+ index = <30>;
+ funcs = "SD1_CLK", "GPIO57", "I2C1_SCL";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad31: PAD_SD1_CD_CFG {
+ index = <31>;
+ funcs = "SD1_CD", "GPIO58", "I2C1_SDA";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad32: PAD_SD1_CMD_RSP_CFG {
+ index = <32>;
+ funcs = "SD1_CMD_RSP", "GPIO59", "UART1_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad33: PAD_SD1_DATA_0_CFG {
+ index = <33>;
+ funcs = "SD1_DATA_0", "GPIO60", "UART1_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad34: PAD_SD1_DATA_1_CFG {
+ index = <34>;
+ funcs = "SD1_DATA_1", "GPIO61", "UART2_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad35: PAD_SD1_DATA_2_CFG {
+ index = <35>;
+ funcs = "SD1_DATA_2", "GPIO62", "UART2_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad36: PAD_SD1_DATA_3_CFG {
+ index = <36>;
+ funcs = "SD1_DATA_3", "GPIO63";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad37: PAD_GPIO_0_CFG {
+ index = <37>;
+ funcs = "ARM_JTAG_TRSTN", "GPIO0", "AC_I2S_DO", "DW_I2S_DO",
+ "SSI1_CLK", "SSI2_CLK", "ACIP_ADDAT", "PWM6",
+ "TEST_O_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad38: PAD_GPIO_1_CFG {
+ index = <38>;
+ funcs = "ARM_JTAG_TDO", "GPIO1", "AC_I2S_DI", "DW_I2S_DI",
+ "SSI1_CSN_0", "SSI2_CSN_0", "ACIP_DADAT", "PWM7",
+ "TEST_O_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad39: PAD_GPIO_2_CFG {
+ index = <39>;
+ funcs = "ARM_JTAG_TDI", "GPIO2", "AC_I2S_CLK", "DW_I2S_CLK",
+ "SSI1_TXD", "SSI2_TXD", "ACIP_ADBCLK", "PWM8",
+ "TEST_O_INT_SMI_MDIO_O";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad40: PAD_GPIO_3_CFG {
+ index = <40>;
+ funcs = "ARM_JTAG_TCK", "GPIO3", "AC_I2S_WS", "DW_I2S_WS",
+ "SSI1_RXD", "SSI2_RXD", "ACIP_ADLRC", "PWM9",
+ "TEST_I_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad41: PAD_GPIO_4_CFG {
+ index = <41>;
+ funcs = "ARM_JTAG_TMS", "GPIO4", "AC_MCLK", "USB_PWREN",
+ "SD1_CD", "TEST_I_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad42: PAD_SSI0_CLK_CFG {
+ index = <42>;
+ funcs = "SSI0_CLK", "GPIO5", "", "", "SD1_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad43: PAD_SSI0_CSN_0_CFG {
+ index = <43>;
+ funcs = "SSI0_CSN_0", "GPIO6", "", "", "SD1_CMD_RSP";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad44: PAD_SSI0_TXD_CFG {
+ index = <44>;
+ funcs = "SSI0_TXD", "GPIO7", "", "", "SD1_DATA_0";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad45: PAD_SSI0_RXD_CFG {
+ index = <45>;
+ funcs = "SSI0_RXD", "GPIO8", "", "", "SD1_DATA_1";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad46: PAD_SSI0_D2_CFG {
+ index = <46>;
+ funcs = "SSI0_D2", "GPIO9", "UART1_TX", "I2C1_SCL",
+ "SD1_DATA_2";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad47: PAD_SSI0_D3_CFG {
+ index = <47>;
+ funcs = "SSI0_D3", "GPIO10", "UART1_RX", "I2C1_SDA",
+ "SD1_DATA_3";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad48: PAD_SSI1_CLK_CFG {
+ index = <48>;
+ funcs = "SSI1_CLK", "GPIO11", "SSI2_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad49: PAD_SSI1_CSN_0_CFG {
+ index = <49>;
+ funcs = "SSI1_CSN_0", "GPIO14", "SSI2_CSN_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad50: PAD_SSI1_TXD_CFG {
+ index = <50>;
+ funcs = "SSI1_TXD", "GPIO15", "SSI2_TXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad51: PAD_SSI1_RXD_CFG {
+ index = <51>;
+ funcs = "SSI1_RXD", "GPIO16", "SSI2_RXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad52: PAD_SD0_CD_CFG {
+ index = <52>;
+ funcs = "SD0_CD", "GPIO17", "", "ARC_JTAG_TRSTN",
+ "PAE_JTAG_TRSTN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad53: PAD_SD0_CLK_CFG {
+ index = <53>;
+ funcs = "SD0_CLK", "GPIO18", "SSI1_CLK", "ARC_JTAG_TDO",
+ "PAE_JTAG_TDO";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad54: PAD_SD0_CMD_RSP_CFG {
+ index = <54>;
+ funcs = "SD0_CMD_RSP", "GPIO19", "SSI1_TXD", "ARC_JTAG_TDI",
+ "PAE_JTAG_TDI";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad55: PAD_SD0_DATA_0_CFG {
+ index = <55>;
+ funcs = "SD0_DATA_0", "GPIO20", "SSI1_RXD", "ARC_JTAG_TCK",
+ "PAE_JTAG_TCK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad56: PAD_SD0_DATA_1_CFG {
+ index = <56>;
+ funcs = "SD0_DATA_1", "GPIO21", "SSI1_CSN_0", "ARC_JTAG_TMS",
+ "PAE_JTAG_TMS";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad57: PAD_SD0_DATA_2_CFG {
+ index = <57>;
+ funcs = "SD0_DATA_2", "GPIO22", "", "UART2_TX", "I2C2_SCL", "",
+ "ACIP_DABCLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad58: PAD_SD0_DATA_3_CFG {
+ index = <58>;
+ funcs = "SD0_DATA_3", "GPIO23", "SSI1_CSN_0", "UART2_RX",
+ "I2C2_SDA", "", "ACIP_DALRC";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad59: PAD_SADC_XAIN0_CFG {
+ index = <59>;
+ funcs = "SADC_XAIN0", "GPIO26";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad60: PAD_SADC_XAIN1_CFG {
+ index = <60>;
+ funcs = "SADC_XAIN1", "GPIO27";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad61: PAD_SADC_XAIN2_CFG {
+ index = <61>;
+ funcs = "SADC_XAIN2", "GPIO24";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad62: PAD_SADC_XAIN3_CFG {
+ index = <62>;
+ funcs = "SADC_XAIN3", "GPIO25";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad63: PAD_GPIO_28_CFG {
+ index = <63>;
+ funcs = "GPIO28", "", "ETH_LINK_ACT", "PWM10",
+ "USB_DBG_CLK", "SD1_CD", "TEST_O_INT_RMII_TXEN",
+ "MAC_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad64: PAD_GPIO_29_CFG {
+ index = <64>;
+ funcs = "GPIO29", "", "ETH_LINK_STA", "PWM11", "RTC_CLK",
+ "ETH_LINK_SPD", "TEST_O_INT_SMI_MDIO_OE",
+ "MAC_MDIO";
+ pupd = <0>;
+ ds = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/fh8856v200.dts b/arch/arm/boot/dts/fh8856v200.dts
new file mode 100644
index 00000000..2a75d423
--- /dev/null
+++ b/arch/arm/boot/dts/fh8856v200.dts
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2017 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+/include/ "fh8856v200_pinctrl.dtsi"
+/ {
+
+
+ model = "FULLHAN FH8856V200";
+ compatible = "fh,fh8856v200";
+ interrupt-parent = <&intc>;
+ aliases {
+ i2c0 = &i2cbus0;
+ i2c1 = &i2cbus1;
+ i2c2 = &i2cbus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ ttyS0 = &serial0;
+ ttyS1 = &serial1;
+ ttyS2 = &serial2;
+ };
+
+ cpus {
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,arm1176jzf-s";
+ };
+ };
+
+ chosen {
+ bootargs = "coherent_pool=2M";
+ };
+
+ intc: interrupt-controller@E0200000 {
+ compatible = "fh,fh-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xE0200000 0x1000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pmu@f0000000 {
+ compatible = "fh,fh-pmu";
+ reg = <0xf0000000 0x2100>;
+ SWRST_MAIN_CTRL = <0x40>;
+ };
+ timer0: timer@f0c00000 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00000 0x14>;
+ };
+
+ timer1: timer@f0c00014 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00014 0x14>;
+ };
+
+ gpio0: gpio@f0300000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf0300000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <26>;
+ id = <0>;
+ ngpio = <32>;
+ base = <0>;
+ };
+
+ gpio1: gpio@f4000000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf4000000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <40>;
+ id = <1>;
+ ngpio = <32>;
+ base = <32>;
+ };
+
+ fhdma0: dma@e0300000 {
+ compatible = "fh,fh-axi-dmac";
+ reg = <0xe0300000 0x1000>;
+ interrupts = <23>;
+ chan_allocation_order = <0>;
+ chan_priority = <1>;
+ block_size = <0x800>;
+ data_width = <2 0 0 0>;
+ clocks = <&ahb_clk>;
+ };
+
+ aes: aes@0xe8200000 {
+ compatible = "fh,fh-aes";
+ reg = <0xe8200000 0x1000>;
+ interrupts = <16>;
+ };
+ rtc: rtc@f1500000 {
+ compatible = "fh,fh_rtc";
+ reg = <0xf1500000 0x1000>;
+ interrupts = <33>;
+ clocks = <&rtc_hclk_gate>;
+ lut_cof = <58>;
+ lut_offset = <0xff>;
+ tsensor_cp_default_out = <0x993>;
+ };
+ sadc: sadc@f1200000 {
+ compatible = "fh,fh-sadc";
+ reg = <0xf1200000 0x1000>;
+ interrupts = <20>;
+ ref-vol = <1800>;
+ active-bit = <0xfff>;
+ };
+ efuse: efuse@0xf1600000 {
+ compatible = "fh,fh-efuse";
+ reg = <0xf1600000 0x1000>;
+ key_switch = "enable";
+ indep_power = "enable";
+ };
+ fh_perf: fh_perf@0xf0002018 {
+ compatible = "fh,fh-perf";
+ reg = <0xf0000000 0x4000>;
+ interrupts = < 5 >;
+
+ };
+ spi_bus0: spi@f0500000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0500000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <6>;
+ cs1_gpio = <55>;
+ dma_enable = "disable";
+ swap_support = "enable";
+ rx_hs_no = <4>;
+ tx_hs_no = <5>;
+ bus_no = <0>;
+ multi_wire_size = <2>;
+ clk_name = "spi0_clk";
+ rx_dma_channel = <0>;
+ tx_dma_channel = <1>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <28>;
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fh,m25p80";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ reg = <0x0 0>; //first value means which slave bind to the master. 0 means chip 0. 1 means chip 1
+ partition@0 {
+ reg = <0x0 0x40000>;
+ label = "bootstrap";
+ };
+ partition@40000 {
+ reg = <0x40000 0x10000>;
+ label = "uboot-env";
+ };
+ partition@50000 {
+ reg = <0x50000 0x30000>;
+ label = "uboot";
+ };
+ partition@80000 {
+ reg = <0x80000 0x400000>;
+ label = "kernel";
+ };
+ partition@480000 {
+ reg = <0x480000 0x80000>;
+ label = "rootfs";
+ };
+ partition@500000 {
+ reg = <0x500000 0x300000>;
+ label = "app";
+ };
+
+ };
+ spidev0: spi@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ spi_bus1: spi@f0600000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0600000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <14>;
+ cs1_gpio = <57>;
+ dma_enable = "disable";
+ swap_support = "disable";
+ rx_hs_no = <2>;
+ tx_hs_no = <3>;
+ bus_no = <1>;
+ clk_name = "spi1_clk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <21>;
+ spidev1: spi@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x0 0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev2: spi@2 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ fhdwi2s: i2s@f0900000 {
+ compatible = "fh,fh-dw_i2s";
+ reg = <0xf0900000 0x1000>;
+ interrupts = <25>;
+ clocks = <&i2s_clk>, <&ac_clk>;
+ clock-names = "i2s_clk", "acodec_mclk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ dma_master = <0>;
+ dma_rx_hs_num = <10>;
+ dma_tx_hs_num = <11>;
+ };
+
+ fhacw: acw@f0a00000 {
+ compatible = "fh,fh-acw";
+ reg = <0xf0a00000 0x1000>;
+ interrupts = <19>;
+ clocks = <&ac_clk>;
+ clock-names = "ac_clk";
+ rx_dma_channel = <4>;
+ tx_dma_channel = <5>;
+ dma_master = <0>;
+ dma_rx_hs_num = <0>;
+ dma_tx_hs_num = <1>;
+ };
+
+ pwm: pwm@f0400000{
+ compatible = "fh,fh-pwm";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <36>;
+ npwm = <14>;
+ };
+ serial0: serial@f0700000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0700000 0x1000>;
+ interrupts = <30>;
+ clock-frequency = <16666667>;
+ fifo-size = <32>;
+ };
+ serial1: serial@f0800000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0800000 0x1000>;
+ interrupts = <31>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ serial2: serial@f1300000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf1300000 0x1000>;
+ interrupts = <41>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ gmac0: gmac@e0600000 {
+ compatible = "fh,fh-gmac";
+ reg = <0xe0600000 0x2000>;
+ interrupts = <44>;
+ phyreset-gpio = <29>;
+ };
+ sdc0: sdc0@e2000000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2000000 0x4000>;
+ interrupts = <42>;
+ id = <0>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <0>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <0>;
+ };
+ sdc1: sdc1@e2200000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2200000 0x4000>;
+ interrupts = <43>;
+ id = <1>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <1>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <2>;
+ };
+ wdt: wdt@f0d00000{
+ compatible = "fh,fh-wdt";
+ reg = <0xf0d00000 0x1000>;
+ interrupts = <2>;
+ mode = <1>;
+ };
+ i2cbus0: i2c@f0200000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0200000 0x2000>;
+ interrupts = <11>;
+ };
+ i2cbus1: i2c@f0b00000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0b00000 0x2000>;
+ interrupts = <12>;
+ };
+ i2cbus2: i2c@0xF0100000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xF0100000 0x2000>;
+ interrupts = <46>;
+ };
+ clocks: src_clk@0xf0000000{
+ compatible = "fh,fh-clk";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf0000000 0x80>;
+ ranges;
+
+ osc_clk: mxtal@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_clk";
+ };
+
+ pll_ddr_rclk: pllddrr{
+ #clock-cells = <0>;
+ compatible = "fh pll-ddr-rclk";
+ reg = <0xf0000010 0x4>,<0xf0000018 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_ddr_rclk";
+ };
+ pll_cpu_pclk: pllcpup{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-pclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_pclk";
+ };
+ pll_cpu_rclk: pllcpur{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-rclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_rclk";
+ };
+ pll_sys_pclk: pllsysp{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-pclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_pclk";
+ };
+ pll_sys_rclk: pllsysr{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-rclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_rclk";
+ };
+ sysp_div12_clk: syspdiv12clk{
+ #clock-cells = <0>;
+ compatible = "fh sysp-div12-clk";
+ reg = <0xf0000038 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sysp_div12_clk";
+ };
+ ddr_clk: ddrclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ddr-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clocks = <&pll_ddr_rclk>;
+ clock-output-names = "ddr_clk";
+ };
+ arm_clk: armclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arm-clk";
+ reg = <0x0 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_pclk>;
+ clock-output-names = "arm_clk";
+ };
+ arc_clk: arcclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arc-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ gate = <0x4000000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_rclk>;
+ clock-output-names = "arc_clk";
+ };
+ ahb_clk: ahbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ahb-clk";
+ reg = <0xf0000024 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ div = <0xf0000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_sys_pclk>;
+ clock-output-names = "ahb_clk";
+ };
+ isp_aclk: ispaclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispa-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00>;
+ gate = <0x1>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "isp_aclk";
+ };
+ ispb_aclk: ispbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispb-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "ispb_aclk";
+ };
+ vpu_clk: vpuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80000000>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "vpu_clk";
+ };
+ pix_clk: pixclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-pix-clk";
+ reg = <0xf000002c 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "pix_clk";
+ };
+ jpeg_clk: jpegclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-clk";
+ reg = <0xf000005c 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "jpeg_clk";
+ };
+ bgm_clk: bgmclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "bgm_clk";
+ };
+ jpeg_adapt_clk: jpegadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-adapt-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2>;
+ clocks = <&jpeg_clk>;
+ clock-output-names = "jpeg_adapt_clk";
+ };
+ spi0_clk: spi0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x80>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi0_clk";
+ };
+ sdc0_clk: sdc0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf00>;
+ gate = <0x200>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc0_clk";
+ };
+ spi2_clk: spi2clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi2-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000>;
+ gate = <0x2>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi2_clk";
+ };
+ spi1_clk: spi1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x100>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi1_clk";
+ };
+ sdc1_clk: sdc1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf000000>;
+ gate = <0x400>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc1_clk";
+ };
+ veu_clk: veuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ div = <0x7000000>;
+ gate = <0x10>;
+ mux = <0x4>;
+ clocks = <&pll_sys_pclk>,<&pll_sys_rclk>;
+ clock-output-names = "veu_clk";
+ };
+ veu_adapt_clk: veuadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-adapt-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clocks = <&veu_clk>;
+ clock-output-names = "veu_adapt_clk";
+ };
+ cis_clk_out: cisclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-cis-clk-out";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x800000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "cis_clk_out";
+ };
+ eth_clk: ethclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-eth-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ gate = <0x2000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "eth_clk";
+ };
+ eth_rmii_clk: ethrmiiclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ethrmii-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "eth_rmii_clk";
+ };
+ i2c0_clk: i2c0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f0000>;
+ gate = <0x1000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c0_clk";
+ };
+
+ i2c1_clk: i2c1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x8000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c1_clk";
+ };
+ i2c2_clk: i2c2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x00000008>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c2_clk";
+ };
+
+ uart0_clk: uart0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f>;
+ gate = <0x2000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart0_clk";
+ };
+
+ uart1_clk: uart1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f00>;
+ gate = <0x4000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart1_clk";
+ };
+ uart2_clk: uart2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f>;
+ gate = <0x8000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart2_clk";
+ };
+ pwm_clk: pwmclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pwm-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x10000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pwm_clk";
+ };
+ efuse_clk: efuseclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-efuse-clk";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x200000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "efuse_clk";
+ };
+ pts_clk: ptsclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pts-clk";
+ reg = <0xf000002c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1ff>;
+ gate = <0x80000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pts_clk";
+ };
+ tmr0_clk: tmr0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-tmr0-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x20000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "tmr0_clk";
+ };
+
+ sadc_clk: sadcclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sadc-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f0000>;
+ gate = <0x4000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "sadc_clk";
+ };
+ gpio0_dbclk: gpio0dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff>;
+ gate = <0x8000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio0_dbclk";
+ };
+ gpio1_dbclk: gpio1dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff0000>;
+ gate = <0x80000000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio1_dbclk";
+ };
+ wdt_clk: wdtclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-wdt-clk";
+ reg = <0xf0000038 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xff00>;
+ gate = <0x8000000>;
+ clocks = <&ahb_clk>;
+ clock-output-names = "wdt_clk";
+ };
+ ac_clk: acclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ac-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f>;
+ gate = <0x800>;
+ clocks = <&osc_clk>;
+ clock-output-names = "ac_clk";
+ };
+ i2s_clk: i2sclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-i2s-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x1000000>;
+ clocks = <&ac_clk>;
+ clock-output-names = "i2s_clk";
+ };
+ mipi_dphy_clk: mipidphyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-dphy-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x100000>;
+ clock-output-names = "mipi_dphy_clk";
+ };
+ mipi_wrap_gate: mipiwrapclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-wrap-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "mipi_wrap_gate";
+ };
+ rtc_hclk_gate: rtchclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-rtc-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "rtc_hclk_gate";
+ };
+ emac_hclk_gate: emachclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-emac-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "emac_hclk_gate";
+ };
+ usb_clk: usbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-usb-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "usb_clk";
+ };
+ aes_hclk_gate: aeshclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-aes-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80>;
+ clock-output-names = "aes_hclk_gate";
+ };
+ ephy_clk_gate: ephyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ephy-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1>;
+ clock-output-names = "ephy_clk_gate";
+ };
+ sdc0_clk8x_gate: sdc08xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc08x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clock-output-names = "sdc0_clk8x_gate";
+ };
+ sdc1_clk8x_gate: sdc18xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc18x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x8>;
+ clock-output-names = "sdc1_clk8x_gate";
+ };
+ mipic_pclk_gate: mipicpclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipic-pclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10>;
+ clock-output-names = "mipic_pclk_gate";
+ };
+ gpio0_pclk_gate: gpio0pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x4000>;
+ clock-output-names = "gpio0_pclk_gate";
+ };
+ gpio1_pclk_gate: gpio1pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "gpio1_pclk_gate";
+ };
+ isp_hclk_gate: isphclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-isp-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "isp_hclk_gate";
+ };
+ veu_hclk_gate: veuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "veu_hclk_gate";
+ };
+ bgm_hclk_gate: bgmhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clock-output-names = "bgm_hclk_gate";
+ };
+ adapt_hclk_gate: adapthclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-adapt-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x8000000>;
+ clock-output-names = "adapt_hclk_gate";
+ };
+ jpg_hclk_gate: jpghclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "jpg_hclk_gate";
+ };
+ jpg_adapt_gate: jpgadaptclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-adapt-clk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "jpg_adapt_gate";
+ };
+ vpu_hclk_gate: vpuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "vpu_hclk_gate";
+ };
+ sdc0_clk_sample: sdc0clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf0000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_sample";
+ };
+ sdc0_clk_drv: sdc0clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_drv";
+ };
+
+ sdc1_clk_sample: sdc1clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_sample";
+ };
+
+ sdc1_clk_drv: sdc1clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf000>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_drv";
+ };
+ };
+ };
+
+ usb_otg@e0700000 {
+ compatible = "fh_usb";
+ reg = <0xe0700000 100000>;
+ interrupts = <39>;
+ clocks = <&usb_clk>;
+ dr_mode = "host";
+ vbus_pwren = <47>;
+ clock-names = "otg";
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
+ };
+
+ usb2_phy: usbphy {
+ compatible = "fh,fh-usb2-phy";
+ #phy-cells = <0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/fh8856v200_pinctrl.dtsi b/arch/arm/boot/dts/fh8856v200_pinctrl.dtsi
new file mode 100644
index 00000000..195479e3
--- /dev/null
+++ b/arch/arm/boot/dts/fh8856v200_pinctrl.dtsi
@@ -0,0 +1,2386 @@
+/*
+ * Copyright (C) 2020 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ #define PUPD_NONE (0)
+ #define PUPD_UP (1)
+ #define PUPD_DOWN (2)
+*/
+
+/ {
+ pinctrl: pinctrl@f0000080 {
+ compatible = "fh,fh-pinctrl";
+ reg = <0xf0000080 0x104>;
+ pad-num = <65>;
+ max-mux = <9>;
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_ETH
+ &pinctrl_I2C0
+ &pinctrl_PWM2
+ &pinctrl_PWM3
+ &pinctrl_PWM4
+ &pinctrl_PWM5
+ &pinctrl_PWM6
+ &pinctrl_PWM7
+ &pinctrl_PWM8
+ &pinctrl_PWM9
+ &pinctrl_SADC_XAIN0
+ &pinctrl_SADC_XAIN1
+ &pinctrl_SD0_NO_WP
+ &pinctrl_SENSOR_CLK
+ &pinctrl_SSI0_4BIT
+ &pinctrl_UART0
+ &pinctrl_UART1
+ &pinctrl_GPIO4
+ &pinctrl_GPIO13
+ &pinctrl_GPIO30
+ &pinctrl_GPIO31
+ &pinctrl_GPIO32
+ &pinctrl_GPIO43
+ &pinctrl_GPIO44
+ &pinctrl_GPIO47
+
+ &pinctrl_GPIO11
+ &pinctrl_GPIO14
+ &pinctrl_GPIO15
+ &pinctrl_GPIO16
+ &pinctrl_GPIO24
+ &pinctrl_GPIO25
+ &pinctrl_GPIO45
+ &pinctrl_GPIO46
+ &pinctrl_GPIO48
+ &pinctrl_GPIO49
+ &pinctrl_GPIO50
+ &pinctrl_GPIO51
+ &pinctrl_GPIO52
+ &pinctrl_GPIO53
+ &pinctrl_GPIO54
+ &pinctrl_GPIO55
+ &pinctrl_GPIO56
+ &pinctrl_GPIO57
+ &pinctrl_GPIO58
+ &pinctrl_GPIO59
+ &pinctrl_GPIO60
+ &pinctrl_GPIO61
+ &pinctrl_GPIO62
+ &pinctrl_GPIO63
+ >;
+ pinctrl_groups {
+ pinctrl_ACI2S: ACI2S {
+ fh,pins = <
+ &mux_AC_I2S_CLK 0
+ &mux_AC_I2S_DI 0
+ &mux_AC_I2S_DO 0
+ &mux_AC_I2S_WS 0
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_AC_MCLK: AC_MCLK {
+ fh,pins = <
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_ARCJTAG: ARCJTAG {
+ fh,pins = <
+ &mux_ARC_JTAG_TCK 0
+ &mux_ARC_JTAG_TDI 0
+ &mux_ARC_JTAG_TDO 0
+ &mux_ARC_JTAG_TMS 0
+ &mux_ARC_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_ARMJTAG: ARMJTAG {
+ fh,pins = <
+ &mux_ARM_JTAG_TCK 0
+ &mux_ARM_JTAG_TDI 0
+ &mux_ARM_JTAG_TDO 0
+ &mux_ARM_JTAG_TMS 0
+ &mux_ARM_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_DWI2S: DWI2S {
+ fh,pins = <
+ &mux_DW_I2S_CLK 0
+ &mux_DW_I2S_DI 0
+ &mux_DW_I2S_DO 0
+ &mux_DW_I2S_WS 0
+ >;
+ };
+ pinctrl_ETH: ETH {
+ fh,pins = <
+ &mux_ETH_LINK_ACT 1
+ &mux_ETH_LINK_STA 1
+ >;
+ };
+ pinctrl_I2C0: I2C0 {
+ fh,pins = <
+ &mux_I2C0_SCL 0
+ &mux_I2C0_SDA 0
+ >;
+ };
+ pinctrl_I2C1: I2C1 {
+ fh,pins = <
+ &mux_I2C1_SCL 2
+ &mux_I2C1_SDA 2
+ >;
+ };
+ pinctrl_I2C2: I2C2 {
+ fh,pins = <
+ &mux_I2C2_SCL 1
+ &mux_I2C2_SDA 1
+ >;
+ };
+ pinctrl_PAEJTAG: PAEJTAG {
+ fh,pins = <
+ &mux_PAE_JTAG_TCK 0
+ &mux_PAE_JTAG_TDI 0
+ &mux_PAE_JTAG_TDO 0
+ &mux_PAE_JTAG_TMS 0
+ &mux_PAE_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_PWM0: PWM0 {
+ fh,pins = <
+ &mux_PWM0 0
+ >;
+ };
+ pinctrl_PWM1: PWM1 {
+ fh,pins = <
+ &mux_PWM1 0
+ >;
+ };
+ pinctrl_PWM10: PWM10 {
+ fh,pins = <
+ &mux_PWM10 0
+ >;
+ };
+ pinctrl_PWM11: PWM11 {
+ fh,pins = <
+ &mux_PWM11 0
+ >;
+ };
+ pinctrl_PWM2: PWM2 {
+ fh,pins = <
+ &mux_PWM2 0
+ >;
+ };
+ pinctrl_PWM3: PWM3 {
+ fh,pins = <
+ &mux_PWM3 0
+ >;
+ };
+ pinctrl_PWM4: PWM4 {
+ fh,pins = <
+ &mux_PWM4 0
+ >;
+ };
+ pinctrl_PWM5: PWM5 {
+ fh,pins = <
+ &mux_PWM5 0
+ >;
+ };
+ pinctrl_PWM6: PWM6 {
+ fh,pins = <
+ &mux_PWM6 1
+ >;
+ };
+ pinctrl_PWM7: PWM7 {
+ fh,pins = <
+ &mux_PWM7 1
+ >;
+ };
+ pinctrl_PWM8: PWM8 {
+ fh,pins = <
+ &mux_PWM8 1
+ >;
+ };
+ pinctrl_PWM9: PWM9 {
+ fh,pins = <
+ &mux_PWM9 1
+ >;
+ };
+ pinctrl_RMII: RMII {
+ fh,pins = <
+ &mux_MAC_MDC 1
+ &mux_MAC_MDIO 1
+ &mux_MAC_REF_CLK 0
+ &mux_MAC_RMII_CLK 0
+ &mux_MAC_RXDV 0
+ &mux_MAC_RXD_0 0
+ &mux_MAC_RXD_1 0
+ &mux_MAC_TXD_0 0
+ &mux_MAC_TXD_1 0
+ &mux_MAC_TXEN 0
+ >;
+ };
+ pinctrl_RTC: RTC {
+ fh,pins = <
+ &mux_RTC_CLK 0
+ >;
+ };
+ pinctrl_SADC_XAIN0: SADC_XAIN0 {
+ fh,pins = <
+ &mux_SADC_XAIN0 0
+ >;
+ };
+ pinctrl_SADC_XAIN1: SADC_XAIN1 {
+ fh,pins = <
+ &mux_SADC_XAIN1 0
+ >;
+ };
+ pinctrl_SADC_XAIN2: SADC_XAIN2 {
+ fh,pins = <
+ &mux_SADC_XAIN2 0
+ >;
+ };
+ pinctrl_SADC_XAIN3: SADC_XAIN3 {
+ fh,pins = <
+ &mux_SADC_XAIN3 0
+ >;
+ };
+ pinctrl_SD0: SD0 {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_1BIT_NO_WP: SD0_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ >;
+ };
+ pinctrl_SD0_NO_WP: SD0_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_WIFI: SD0_WIFI {
+ fh,pins = <
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD1: SD1 {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_1BIT_NO_WP: SD1_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ >;
+ };
+ pinctrl_SD1_NO_WP: SD1_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_WIFI: SD1_WIFI {
+ fh,pins = <
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SENSOR_CLK: SENSOR_CLK {
+ fh,pins = <
+ &mux_SENSOR_CLK 0
+ >;
+ };
+ pinctrl_SSI0: SSI0 {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI0_4BIT: SSI0_4BIT {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_D2 0
+ &mux_SSI0_D3 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI1: SSI1 {
+ fh,pins = <
+ &mux_GPIO14 0
+ &mux_SSI1_CLK 2
+ &mux_SSI1_RXD 2
+ &mux_SSI1_TXD 2
+ >;
+ };
+ pinctrl_SSI2: SSI2 {
+ fh,pins = <
+ &mux_SSI2_CLK 1
+ &mux_SSI2_CSN_0 1
+ &mux_SSI2_RXD 1
+ &mux_SSI2_TXD 1
+ >;
+ };
+ pinctrl_UART0: UART0 {
+ fh,pins = <
+ &mux_UART0_RX 0
+ &mux_UART0_TX 0
+ >;
+ };
+ pinctrl_UART1: UART1 {
+ fh,pins = <
+ &mux_UART1_RX 0
+ &mux_UART1_TX 0
+ >;
+ };
+ pinctrl_UART2: UART2 {
+ fh,pins = <
+ &mux_UART2_RX 0
+ &mux_UART2_TX 0
+ >;
+ };
+ pinctrl_USB: USB {
+ fh,pins = <
+ &mux_USB_PWREN 0
+ >;
+ };
+ pinctrl_GPIO0: GPIO0 {
+ fh,pins = <
+ &mux_GPIO0 0
+ >;
+ };
+ pinctrl_GPIO1: GPIO1 {
+ fh,pins = <
+ &mux_GPIO1 0
+ >;
+ };
+ pinctrl_GPIO2: GPIO2 {
+ fh,pins = <
+ &mux_GPIO2 0
+ >;
+ };
+ pinctrl_GPIO3: GPIO3 {
+ fh,pins = <
+ &mux_GPIO3 0
+ >;
+ };
+ pinctrl_GPIO4: GPIO4 {
+ fh,pins = <
+ &mux_GPIO4 0
+ >;
+ };
+ pinctrl_GPIO5: GPIO5 {
+ fh,pins = <
+ &mux_GPIO5 0
+ >;
+ };
+ pinctrl_GPIO6: GPIO6 {
+ fh,pins = <
+ &mux_GPIO6 0
+ >;
+ };
+ pinctrl_GPIO7: GPIO7 {
+ fh,pins = <
+ &mux_GPIO7 0
+ >;
+ };
+ pinctrl_GPIO8: GPIO8 {
+ fh,pins = <
+ &mux_GPIO8 0
+ >;
+ };
+ pinctrl_GPIO9: GPIO9 {
+ fh,pins = <
+ &mux_GPIO9 0
+ >;
+ };
+ pinctrl_GPIO10: GPIO10 {
+ fh,pins = <
+ &mux_GPIO10 0
+ >;
+ };
+ pinctrl_GPIO11: GPIO11 {
+ fh,pins = <
+ &mux_GPIO11 0
+ >;
+ };
+ pinctrl_GPIO12: GPIO12 {
+ fh,pins = <
+ &mux_GPIO12 0
+ >;
+ };
+ pinctrl_GPIO13: GPIO13 {
+ fh,pins = <
+ &mux_GPIO13 0
+ >;
+ };
+ pinctrl_GPIO14: GPIO14 {
+ fh,pins = <
+ &mux_GPIO14 0
+ >;
+ };
+ pinctrl_GPIO15: GPIO15 {
+ fh,pins = <
+ &mux_GPIO15 0
+ >;
+ };
+ pinctrl_GPIO16: GPIO16 {
+ fh,pins = <
+ &mux_GPIO16 0
+ >;
+ };
+ pinctrl_GPIO17: GPIO17 {
+ fh,pins = <
+ &mux_GPIO17 0
+ >;
+ };
+ pinctrl_GPIO18: GPIO18 {
+ fh,pins = <
+ &mux_GPIO18 0
+ >;
+ };
+ pinctrl_GPIO19: GPIO19 {
+ fh,pins = <
+ &mux_GPIO19 0
+ >;
+ };
+ pinctrl_GPIO20: GPIO20 {
+ fh,pins = <
+ &mux_GPIO20 0
+ >;
+ };
+ pinctrl_GPIO21: GPIO21 {
+ fh,pins = <
+ &mux_GPIO21 0
+ >;
+ };
+ pinctrl_GPIO22: GPIO22 {
+ fh,pins = <
+ &mux_GPIO22 0
+ >;
+ };
+ pinctrl_GPIO23: GPIO23 {
+ fh,pins = <
+ &mux_GPIO23 0
+ >;
+ };
+ pinctrl_GPIO24: GPIO24 {
+ fh,pins = <
+ &mux_GPIO24 0
+ >;
+ };
+ pinctrl_GPIO25: GPIO25 {
+ fh,pins = <
+ &mux_GPIO25 0
+ >;
+ };
+ pinctrl_GPIO26: GPIO26 {
+ fh,pins = <
+ &mux_GPIO26 0
+ >;
+ };
+ pinctrl_GPIO27: GPIO27 {
+ fh,pins = <
+ &mux_GPIO27 0
+ >;
+ };
+ pinctrl_GPIO28: GPIO28 {
+ fh,pins = <
+ &mux_GPIO28 0
+ >;
+ };
+ pinctrl_GPIO29: GPIO29 {
+ fh,pins = <
+ &mux_GPIO29 0
+ >;
+ };
+ pinctrl_GPIO30: GPIO30 {
+ fh,pins = <
+ &mux_GPIO30 0
+ >;
+ };
+ pinctrl_GPIO31: GPIO31 {
+ fh,pins = <
+ &mux_GPIO31 0
+ >;
+ };
+ pinctrl_GPIO32: GPIO32 {
+ fh,pins = <
+ &mux_GPIO32 0
+ >;
+ };
+ pinctrl_GPIO33: GPIO33 {
+ fh,pins = <
+ &mux_GPIO33 0
+ >;
+ };
+ pinctrl_GPIO34: GPIO34 {
+ fh,pins = <
+ &mux_GPIO34 0
+ >;
+ };
+ pinctrl_GPIO35: GPIO35 {
+ fh,pins = <
+ &mux_GPIO35 0
+ >;
+ };
+ pinctrl_GPIO36: GPIO36 {
+ fh,pins = <
+ &mux_GPIO36 0
+ >;
+ };
+ pinctrl_GPIO37: GPIO37 {
+ fh,pins = <
+ &mux_GPIO37 0
+ >;
+ };
+ pinctrl_GPIO38: GPIO38 {
+ fh,pins = <
+ &mux_GPIO38 0
+ >;
+ };
+ pinctrl_GPIO39: GPIO39 {
+ fh,pins = <
+ &mux_GPIO39 0
+ >;
+ };
+ pinctrl_GPIO40: GPIO40 {
+ fh,pins = <
+ &mux_GPIO40 0
+ >;
+ };
+ pinctrl_GPIO41: GPIO41 {
+ fh,pins = <
+ &mux_GPIO41 0
+ >;
+ };
+ pinctrl_GPIO42: GPIO42 {
+ fh,pins = <
+ &mux_GPIO42 0
+ >;
+ };
+ pinctrl_GPIO43: GPIO43 {
+ fh,pins = <
+ &mux_GPIO43 0
+ >;
+ };
+ pinctrl_GPIO44: GPIO44 {
+ fh,pins = <
+ &mux_GPIO44 0
+ >;
+ };
+ pinctrl_GPIO45: GPIO45 {
+ fh,pins = <
+ &mux_GPIO45 0
+ >;
+ };
+ pinctrl_GPIO46: GPIO46 {
+ fh,pins = <
+ &mux_GPIO46 0
+ >;
+ };
+ pinctrl_GPIO47: GPIO47 {
+ fh,pins = <
+ &mux_GPIO47 0
+ >;
+ };
+ pinctrl_GPIO48: GPIO48 {
+ fh,pins = <
+ &mux_GPIO48 0
+ >;
+ };
+ pinctrl_GPIO49: GPIO49 {
+ fh,pins = <
+ &mux_GPIO49 0
+ >;
+ };
+ pinctrl_GPIO50: GPIO50 {
+ fh,pins = <
+ &mux_GPIO50 0
+ >;
+ };
+ pinctrl_GPIO51: GPIO51 {
+ fh,pins = <
+ &mux_GPIO51 0
+ >;
+ };
+ pinctrl_GPIO52: GPIO52 {
+ fh,pins = <
+ &mux_GPIO52 0
+ >;
+ };
+ pinctrl_GPIO53: GPIO53 {
+ fh,pins = <
+ &mux_GPIO53 0
+ >;
+ };
+ pinctrl_GPIO54: GPIO54 {
+ fh,pins = <
+ &mux_GPIO54 0
+ >;
+ };
+ pinctrl_GPIO55: GPIO55 {
+ fh,pins = <
+ &mux_GPIO55 0
+ >;
+ };
+ pinctrl_GPIO56: GPIO56 {
+ fh,pins = <
+ &mux_GPIO56 0
+ >;
+ };
+ pinctrl_GPIO57: GPIO57 {
+ fh,pins = <
+ &mux_GPIO57 0
+ >;
+ };
+ pinctrl_GPIO58: GPIO58 {
+ fh,pins = <
+ &mux_GPIO58 0
+ >;
+ };
+ pinctrl_GPIO59: GPIO59 {
+ fh,pins = <
+ &mux_GPIO59 0
+ >;
+ };
+ pinctrl_GPIO60: GPIO60 {
+ fh,pins = <
+ &mux_GPIO60 0
+ >;
+ };
+ pinctrl_GPIO61: GPIO61 {
+ fh,pins = <
+ &mux_GPIO61 0
+ >;
+ };
+ pinctrl_GPIO62: GPIO62 {
+ fh,pins = <
+ &mux_GPIO62 0
+ >;
+ };
+ pinctrl_GPIO63: GPIO63 {
+ fh,pins = <
+ &mux_GPIO63 0
+ >;
+ };
+ pinctrl_SD1_EMMC: SD1_EMMC {
+ fh,pins = <
+ &mux_SD1_CD 3
+ &mux_SD1_CLK 3
+ &mux_SD1_CMD_RSP 3
+ &mux_SD1_DATA_0 3
+ &mux_SD1_DATA_1 3
+ &mux_SD1_DATA_2 3
+ &mux_SD1_DATA_3 3
+ >;
+ };
+ };
+ pinmux: pinmux {
+ compatible = "fh,fh-pinmux";
+ #list-cells = <1>;
+ mux_AC_I2S_CLK: AC_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_AC_I2S_DI: AC_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_AC_I2S_DO: AC_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_AC_I2S_WS: AC_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_AC_MCLK: AC_MCLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+
+ mux_ARC_JTAG_TCK: ARC_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_ARC_JTAG_TDI: ARC_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_ARC_JTAG_TDO: ARC_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_ARC_JTAG_TMS: ARC_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_ARC_JTAG_TRSTN: ARC_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_ARM_JTAG_TCK: ARM_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_ARM_JTAG_TDI: ARM_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_ARM_JTAG_TDO: ARM_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_ARM_JTAG_TMS: ARM_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_ARM_JTAG_TRSTN: ARM_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+
+ mux_DW_I2S_CLK: DW_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_DW_I2S_DI: DW_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_DW_I2S_DO: DW_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_DW_I2S_WS: DW_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+
+ mux_ETH_LINK_ACT: ETH_LINK_ACT {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad1
+ &pad63
+ >;
+ };
+ mux_ETH_LINK_SPD: ETH_LINK_SPD {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+ mux_ETH_LINK_STA: ETH_LINK_STA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+
+ mux_I2C0_SCL: I2C0_SCL {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_I2C0_SDA: I2C0_SDA {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+
+ mux_I2C1_SCL: I2C1_SCL {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad11
+ &pad30
+ &pad46
+ >;
+ };
+ mux_I2C1_SDA: I2C1_SDA {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad12
+ &pad31
+ &pad47
+ >;
+ };
+
+ mux_I2C2_SCL: I2C2_SCL {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad16
+ &pad57
+ >;
+ };
+ mux_I2C2_SDA: I2C2_SDA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad17
+ &pad58
+ >;
+ };
+
+ mux_MAC_MDC: MAC_MDC {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad28
+ &pad63
+ >;
+ };
+ mux_MAC_MDIO: MAC_MDIO {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad29
+ &pad64
+ >;
+ };
+ mux_MAC_REF_CLK: MAC_REF_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad21
+ >;
+ };
+ mux_MAC_RMII_CLK: MAC_RMII_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_MAC_RXDV: MAC_RXDV {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_MAC_RXD_0: MAC_RXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_MAC_RXD_1: MAC_RXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_MAC_TXD_0: MAC_TXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_MAC_TXD_1: MAC_TXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_MAC_TXEN: MAC_TXEN {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+
+ mux_PAE_JTAG_TCK: PAE_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_PAE_JTAG_TDI: PAE_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_PAE_JTAG_TDO: PAE_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_PAE_JTAG_TMS: PAE_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_PAE_JTAG_TRSTN: PAE_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_PWM0: PWM0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_PWM1: PWM1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_PWM10: PWM10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_PWM11: PWM11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_PWM2: PWM2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ &pad18
+ &pad20
+ >;
+ };
+ mux_PWM3: PWM3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ &pad19
+ &pad22
+ >;
+ };
+ mux_PWM4: PWM4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad23
+ >;
+ };
+ mux_PWM5: PWM5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad24
+ >;
+ };
+ mux_PWM6: PWM6 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad25
+ &pad37
+ >;
+ };
+ mux_PWM7: PWM7 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad26
+ &pad38
+ >;
+ };
+ mux_PWM8: PWM8 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad27
+ &pad39
+ >;
+ };
+ mux_PWM9: PWM9 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad28
+ &pad40
+ >;
+ };
+
+ mux_RTC_CLK: RTC_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+
+ mux_SADC_XAIN0: SADC_XAIN0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_SADC_XAIN1: SADC_XAIN1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_SADC_XAIN2: SADC_XAIN2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_SADC_XAIN3: SADC_XAIN3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+
+ mux_SD0_CD: SD0_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_SD0_CLK: SD0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_SD0_CMD_RSP: SD0_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_SD0_DATA_0: SD0_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_SD0_DATA_1: SD0_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_SD0_DATA_2: SD0_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_SD0_DATA_3: SD0_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+
+ mux_SD1_CD: SD1_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad10
+ &pad22
+ &pad31
+ &pad41
+ &pad63
+ >;
+ };
+ mux_SD1_CLK: SD1_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad9
+ &pad20
+ &pad30
+ &pad42
+ >;
+ };
+ mux_SD1_CMD_RSP: SD1_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad23
+ &pad32
+ &pad43
+ >;
+ };
+ mux_SD1_DATA_0: SD1_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad12
+ &pad24
+ &pad33
+ &pad44
+ >;
+ };
+ mux_SD1_DATA_1: SD1_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad25
+ &pad34
+ &pad45
+ >;
+ };
+ mux_SD1_DATA_2: SD1_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad26
+ &pad35
+ &pad46
+ >;
+ };
+ mux_SD1_DATA_3: SD1_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad15
+ &pad27
+ &pad36
+ &pad47
+ >;
+ };
+
+ mux_SENSOR_CLK: SENSOR_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+
+ mux_SSI0_CLK: SSI0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_SSI0_D2: SSI0_D2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_SSI0_D3: SSI0_D3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_SSI0_RXD: SSI0_RXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_SSI0_TXD: SSI0_TXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+
+ mux_SSI1_CLK: SSI1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad37
+ &pad48
+ &pad53
+ >;
+ };
+ mux_SSI1_RXD: SSI1_RXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad40
+ &pad51
+ &pad55
+ >;
+ };
+ mux_SSI1_TXD: SSI1_TXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad39
+ &pad50
+ &pad54
+ >;
+ };
+
+ mux_SSI2_CLK: SSI2_CLK {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad37
+ &pad48
+ >;
+ };
+ mux_SSI2_CSN_0: SSI2_CSN_0 {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad38
+ &pad49
+ >;
+ };
+ mux_SSI2_RXD: SSI2_RXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad40
+ &pad51
+ >;
+ };
+ mux_SSI2_TXD: SSI2_TXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad39
+ &pad50
+ >;
+ };
+
+ mux_UART0_RX: UART0_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_UART0_TX: UART0_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+
+ mux_UART1_RX: UART1_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ &pad33
+ &pad47
+ >;
+ };
+ mux_UART1_TX: UART1_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ &pad32
+ &pad46
+ >;
+ };
+
+ mux_UART2_RX: UART2_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad17
+ &pad35
+ &pad58
+ >;
+ };
+ mux_UART2_TX: UART2_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad16
+ &pad34
+ &pad57
+ >;
+ };
+
+ mux_USB_PWREN: USB_PWREN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ &pad41
+ >;
+ };
+
+ mux_GPIO0: GPIO0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_GPIO1: GPIO1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_GPIO2: GPIO2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_GPIO3: GPIO3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_GPIO4: GPIO4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_GPIO5: GPIO5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_GPIO6: GPIO6 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad43
+ >;
+ };
+ mux_GPIO7: GPIO7 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+ mux_GPIO8: GPIO8 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_GPIO9: GPIO9 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_GPIO10: GPIO10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_GPIO11: GPIO11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad48
+ >;
+ };
+ mux_GPIO12: GPIO12 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+ mux_GPIO13: GPIO13 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad8
+ >;
+ };
+ mux_GPIO14: GPIO14 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad49
+ >;
+ };
+ mux_GPIO15: GPIO15 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad50
+ >;
+ };
+ mux_GPIO16: GPIO16 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad51
+ >;
+ };
+ mux_GPIO17: GPIO17 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_GPIO18: GPIO18 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_GPIO19: GPIO19 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_GPIO20: GPIO20 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_GPIO21: GPIO21 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_GPIO22: GPIO22 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_GPIO23: GPIO23 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+ mux_GPIO24: GPIO24 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_GPIO25: GPIO25 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+ mux_GPIO26: GPIO26 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_GPIO27: GPIO27 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_GPIO28: GPIO28 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_GPIO29: GPIO29 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_GPIO30: GPIO30 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad0
+ >;
+ };
+ mux_GPIO31: GPIO31 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad1
+ >;
+ };
+ mux_GPIO32: GPIO32 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad2
+ >;
+ };
+ mux_GPIO33: GPIO33 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+ mux_GPIO34: GPIO34 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_GPIO35: GPIO35 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_GPIO36: GPIO36 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+ mux_GPIO37: GPIO37 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ >;
+ };
+ mux_GPIO38: GPIO38 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ >;
+ };
+ mux_GPIO39: GPIO39 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ >;
+ };
+ mux_GPIO40: GPIO40 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ >;
+ };
+ mux_GPIO41: GPIO41 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ >;
+ };
+ mux_GPIO42: GPIO42 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ >;
+ };
+ mux_GPIO43: GPIO43 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_GPIO44: GPIO44 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_GPIO45: GPIO45 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad18
+ >;
+ };
+ mux_GPIO46: GPIO46 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad19
+ >;
+ };
+ mux_GPIO47: GPIO47 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ >;
+ };
+ mux_GPIO48: GPIO48 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_GPIO49: GPIO49 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_GPIO50: GPIO50 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_GPIO51: GPIO51 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+ mux_GPIO52: GPIO52 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_GPIO53: GPIO53 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_GPIO54: GPIO54 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_GPIO55: GPIO55 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad28
+ >;
+ };
+ mux_GPIO56: GPIO56 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad29
+ >;
+ };
+ mux_GPIO57: GPIO57 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad30
+ >;
+ };
+ mux_GPIO58: GPIO58 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad31
+ >;
+ };
+ mux_GPIO59: GPIO59 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad32
+ >;
+ };
+ mux_GPIO60: GPIO60 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad33
+ >;
+ };
+ mux_GPIO61: GPIO61 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad34
+ >;
+ };
+ mux_GPIO62: GPIO62 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad35
+ >;
+ };
+ mux_GPIO63: GPIO63 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad36
+ >;
+ };
+ };
+ pinpad: pinpad {
+ compatible = "fh,fh-pinpad";
+ pad0: PAD_BOOT_MODE_CFG {
+ index = <0>;
+ funcs = "GPIO30";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad1: PAD_BOOT_SEL1_CFG {
+ index = <1>;
+ funcs = "GPIO31", "ETH_LINK_ACT";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad2: PAD_BOOT_SEL0_CFG {
+ index = <2>;
+ funcs = "GPIO32", "ETH_LINK_STA", "ETH_LINK_SPD";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad3: PAD_UART0_TX_CFG {
+ index = <3>;
+ funcs = "UART0_TX", "GPIO33";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad4: PAD_UART0_RX_CFG {
+ index = <4>;
+ funcs = "UART0_RX", "GPIO34";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad5: PAD_I2C0_SCL_CFG {
+ index = <5>;
+ funcs = "I2C0_SCL", "GPIO35";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad6: PAD_I2C0_SDA_CFG {
+ index = <6>;
+ funcs = "I2C0_SDA", "GPIO36";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad7: PAD_SENSOR_CLK_CFG {
+ index = <7>;
+ funcs = "SENSOR_CLK", "GPIO12";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad8: PAD_SENSOR_RSTN_CFG {
+ index = <8>;
+ funcs = "GPIO13";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad9: PAD_UART1_TX_CFG {
+ index = <9>;
+ funcs = "UART1_TX", "GPIO39", "", "SD1_CLK", "", "",
+ "TEST_O_INT_RMII_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad10: PAD_UART1_RX_CFG {
+ index = <10>;
+ funcs = "UART1_RX", "GPIO40", "", "SD1_CD", "", "",
+ "TEST_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad11: PAD_I2C1_SCL_CFG {
+ index = <11>;
+ funcs = "I2C1_SCL", "GPIO37", "PWM2", "SD1_CMD_RSP", "",
+ "SSI1_CLK", "TEST_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad12: PAD_I2C1_SDA_CFG {
+ index = <12>;
+ funcs = "I2C1_SDA", "GPIO38", "PWM3", "SD1_DATA_0", "",
+ "SSI1_CSN_0", "TEST_INT_RMII_TXEN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad13: PAD_UART2_TX_CFG {
+ index = <13>;
+ funcs = "UART2_TX", "GPIO41", "PWM4", "SD1_DATA_1", "",
+ "SSI1_TXD", "TEST_O_INT_RMII_RXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad14: PAD_UART2_RX_CFG {
+ index = <14>;
+ funcs = "UART2_RX", "GPIO42", "PWM5", "SD1_DATA_2", "",
+ "SSI1_RXD", "TEST_O_INT_RMII_RXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad15: PAD_USB_PWREN_CFG {
+ index = <15>;
+ funcs = "USB_PWREN", "GPIO47", "", "SD1_DATA_3", "", "",
+ "TEST_O_INT_RMII_CRSDV";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad16: PAD_PWM0_CFG {
+ index = <16>;
+ funcs = "PWM0", "GPIO43", "I2C2_SCL", "UART2_TX", "", "",
+ "TEST_O_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad17: PAD_PWM1_CFG {
+ index = <17>;
+ funcs = "PWM1", "GPIO44", "I2C2_SDA", "UART2_RX", "", "",
+ "TEST_O_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad18: PAD_PWM2_CFG {
+ index = <18>;
+ funcs = "PWM2", "GPIO45";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad19: PAD_PWM3_CFG {
+ index = <19>;
+ funcs = "PWM3", "GPIO46";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad20: PAD_MAC_RMII_CLK_CFG {
+ index = <20>;
+ funcs = "MAC_RMII_CLK", "GPIO48", "SD1_CLK", "PWM2";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad21: PAD_MAC_REF_CLK_CFG {
+ index = <21>;
+ funcs = "MAC_REF_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad22: PAD_MAC_TXD0_CFG {
+ index = <22>;
+ funcs = "MAC_TXD_0", "GPIO49", "SD1_CD", "PWM3";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad23: PAD_MAC_TXD1_CFG {
+ index = <23>;
+ funcs = "MAC_TXD_1", "GPIO50", "SD1_CMD_RSP", "PWM4";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad24: PAD_MAC_TXEN_CFG {
+ index = <24>;
+ funcs = "MAC_TXEN", "GPIO51", "SD1_DATA_0", "PWM5";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad25: PAD_MAC_RXD0_CFG {
+ index = <25>;
+ funcs = "MAC_RXD_0", "GPIO52", "SD1_DATA_1", "PWM6";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad26: PAD_MAC_RXD1_CFG {
+ index = <26>;
+ funcs = "MAC_RXD_1", "GPIO53", "SD1_DATA_2", "PWM7";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad27: PAD_MAC_RXDV_CFG {
+ index = <27>;
+ funcs = "MAC_RXDV", "GPIO54", "SD1_DATA_3", "PWM8";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad28: PAD_MAC_MDC_CFG {
+ index = <28>;
+ funcs = "MAC_MDC", "GPIO55", "", "PWM9";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad29: PAD_MAC_MDIO_CFG {
+ index = <29>;
+ funcs = "MAC_MDIO", "GPIO56";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad30: PAD_SD1_CLK_CFG {
+ index = <30>;
+ funcs = "SD1_CLK", "GPIO57", "I2C1_SCL";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad31: PAD_SD1_CD_CFG {
+ index = <31>;
+ funcs = "SD1_CD", "GPIO58", "I2C1_SDA";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad32: PAD_SD1_CMD_RSP_CFG {
+ index = <32>;
+ funcs = "SD1_CMD_RSP", "GPIO59", "UART1_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad33: PAD_SD1_DATA_0_CFG {
+ index = <33>;
+ funcs = "SD1_DATA_0", "GPIO60", "UART1_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad34: PAD_SD1_DATA_1_CFG {
+ index = <34>;
+ funcs = "SD1_DATA_1", "GPIO61", "UART2_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad35: PAD_SD1_DATA_2_CFG {
+ index = <35>;
+ funcs = "SD1_DATA_2", "GPIO62", "UART2_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad36: PAD_SD1_DATA_3_CFG {
+ index = <36>;
+ funcs = "SD1_DATA_3", "GPIO63";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad37: PAD_GPIO_0_CFG {
+ index = <37>;
+ funcs = "ARM_JTAG_TRSTN", "GPIO0", "AC_I2S_DO", "DW_I2S_DO",
+ "SSI1_CLK", "SSI2_CLK", "ACIP_ADDAT", "PWM6",
+ "TEST_O_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad38: PAD_GPIO_1_CFG {
+ index = <38>;
+ funcs = "ARM_JTAG_TDO", "GPIO1", "AC_I2S_DI", "DW_I2S_DI",
+ "SSI1_CSN_0", "SSI2_CSN_0", "ACIP_DADAT", "PWM7",
+ "TEST_O_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad39: PAD_GPIO_2_CFG {
+ index = <39>;
+ funcs = "ARM_JTAG_TDI", "GPIO2", "AC_I2S_CLK", "DW_I2S_CLK",
+ "SSI1_TXD", "SSI2_TXD", "ACIP_ADBCLK", "PWM8",
+ "TEST_O_INT_SMI_MDIO_O";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad40: PAD_GPIO_3_CFG {
+ index = <40>;
+ funcs = "ARM_JTAG_TCK", "GPIO3", "AC_I2S_WS", "DW_I2S_WS",
+ "SSI1_RXD", "SSI2_RXD", "ACIP_ADLRC", "PWM9",
+ "TEST_I_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad41: PAD_GPIO_4_CFG {
+ index = <41>;
+ funcs = "ARM_JTAG_TMS", "GPIO4", "AC_MCLK", "USB_PWREN",
+ "SD1_CD", "TEST_I_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad42: PAD_SSI0_CLK_CFG {
+ index = <42>;
+ funcs = "SSI0_CLK", "GPIO5", "", "", "SD1_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad43: PAD_SSI0_CSN_0_CFG {
+ index = <43>;
+ funcs = "SSI0_CSN_0", "GPIO6", "", "", "SD1_CMD_RSP";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad44: PAD_SSI0_TXD_CFG {
+ index = <44>;
+ funcs = "SSI0_TXD", "GPIO7", "", "", "SD1_DATA_0";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad45: PAD_SSI0_RXD_CFG {
+ index = <45>;
+ funcs = "SSI0_RXD", "GPIO8", "", "", "SD1_DATA_1";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad46: PAD_SSI0_D2_CFG {
+ index = <46>;
+ funcs = "SSI0_D2", "GPIO9", "UART1_TX", "I2C1_SCL",
+ "SD1_DATA_2";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad47: PAD_SSI0_D3_CFG {
+ index = <47>;
+ funcs = "SSI0_D3", "GPIO10", "UART1_RX", "I2C1_SDA",
+ "SD1_DATA_3";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad48: PAD_SSI1_CLK_CFG {
+ index = <48>;
+ funcs = "SSI1_CLK", "GPIO11", "SSI2_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad49: PAD_SSI1_CSN_0_CFG {
+ index = <49>;
+ funcs = "SSI1_CSN_0", "GPIO14", "SSI2_CSN_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad50: PAD_SSI1_TXD_CFG {
+ index = <50>;
+ funcs = "SSI1_TXD", "GPIO15", "SSI2_TXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad51: PAD_SSI1_RXD_CFG {
+ index = <51>;
+ funcs = "SSI1_RXD", "GPIO16", "SSI2_RXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad52: PAD_SD0_CD_CFG {
+ index = <52>;
+ funcs = "SD0_CD", "GPIO17", "", "ARC_JTAG_TRSTN",
+ "PAE_JTAG_TRSTN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad53: PAD_SD0_CLK_CFG {
+ index = <53>;
+ funcs = "SD0_CLK", "GPIO18", "SSI1_CLK", "ARC_JTAG_TDO",
+ "PAE_JTAG_TDO";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad54: PAD_SD0_CMD_RSP_CFG {
+ index = <54>;
+ funcs = "SD0_CMD_RSP", "GPIO19", "SSI1_TXD", "ARC_JTAG_TDI",
+ "PAE_JTAG_TDI";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad55: PAD_SD0_DATA_0_CFG {
+ index = <55>;
+ funcs = "SD0_DATA_0", "GPIO20", "SSI1_RXD", "ARC_JTAG_TCK",
+ "PAE_JTAG_TCK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad56: PAD_SD0_DATA_1_CFG {
+ index = <56>;
+ funcs = "SD0_DATA_1", "GPIO21", "SSI1_CSN_0", "ARC_JTAG_TMS",
+ "PAE_JTAG_TMS";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad57: PAD_SD0_DATA_2_CFG {
+ index = <57>;
+ funcs = "SD0_DATA_2", "GPIO22", "", "UART2_TX", "I2C2_SCL", "",
+ "ACIP_DABCLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad58: PAD_SD0_DATA_3_CFG {
+ index = <58>;
+ funcs = "SD0_DATA_3", "GPIO23", "SSI1_CSN_0", "UART2_RX",
+ "I2C2_SDA", "", "ACIP_DALRC";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad59: PAD_SADC_XAIN0_CFG {
+ index = <59>;
+ funcs = "SADC_XAIN0", "GPIO26";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad60: PAD_SADC_XAIN1_CFG {
+ index = <60>;
+ funcs = "SADC_XAIN1", "GPIO27";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad61: PAD_SADC_XAIN2_CFG {
+ index = <61>;
+ funcs = "SADC_XAIN2", "GPIO24";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad62: PAD_SADC_XAIN3_CFG {
+ index = <62>;
+ funcs = "SADC_XAIN3", "GPIO25";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad63: PAD_GPIO_28_CFG {
+ index = <63>;
+ funcs = "GPIO28", "", "ETH_LINK_ACT", "PWM10",
+ "USB_DBG_CLK", "SD1_CD", "TEST_O_INT_RMII_TXEN",
+ "MAC_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad64: PAD_GPIO_29_CFG {
+ index = <64>;
+ funcs = "GPIO29", "", "ETH_LINK_STA", "PWM11", "RTC_CLK",
+ "ETH_LINK_SPD", "TEST_O_INT_SMI_MDIO_OE",
+ "MAC_MDIO";
+ pupd = <0>;
+ ds = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/fh8856v210.dts b/arch/arm/boot/dts/fh8856v210.dts
new file mode 100644
index 00000000..f9ebb035
--- /dev/null
+++ b/arch/arm/boot/dts/fh8856v210.dts
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2017 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+/include/ "fh8856v210_pinctrl.dtsi"
+/ {
+
+
+ model = "FULLHAN FH8856V210";
+ compatible = "fh,fh8856v210";
+ interrupt-parent = <&intc>;
+ aliases {
+ i2c0 = &i2cbus0;
+ i2c1 = &i2cbus1;
+ i2c2 = &i2cbus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ ttyS0 = &serial0;
+ ttyS1 = &serial1;
+ ttyS2 = &serial2;
+ };
+
+ cpus {
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,arm1176jzf-s";
+ };
+ };
+
+ chosen {
+ bootargs = "coherent_pool=2M";
+ };
+
+ intc: interrupt-controller@E0200000 {
+ compatible = "fh,fh-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xE0200000 0x1000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pmu@f0000000 {
+ compatible = "fh,fh-pmu";
+ reg = <0xf0000000 0x2100>;
+ SWRST_MAIN_CTRL = <0x40>;
+ };
+ timer0: timer@f0c00000 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00000 0x14>;
+ };
+
+ timer1: timer@f0c00014 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00014 0x14>;
+ };
+
+ gpio0: gpio@f0300000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf0300000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <26>;
+ id = <0>;
+ ngpio = <32>;
+ base = <0>;
+ };
+
+ gpio1: gpio@f4000000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf4000000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <40>;
+ id = <1>;
+ ngpio = <32>;
+ base = <32>;
+ };
+
+ fhdma0: dma@e0300000 {
+ compatible = "fh,fh-axi-dmac";
+ reg = <0xe0300000 0x1000>;
+ interrupts = <23>;
+ chan_allocation_order = <0>;
+ chan_priority = <1>;
+ block_size = <0x800>;
+ data_width = <2 0 0 0>;
+ clocks = <&ahb_clk>;
+ };
+
+ aes: aes@0xe8200000 {
+ compatible = "fh,fh-aes";
+ reg = <0xe8200000 0x1000>;
+ interrupts = <16>;
+ };
+ rtc: rtc@f1500000 {
+ compatible = "fh,fh_rtc";
+ reg = <0xf1500000 0x1000>;
+ interrupts = <33>;
+ clocks = <&rtc_hclk_gate>;
+ lut_cof = <71>;
+ lut_offset = <0xf6>;
+ tsensor_cp_default_out = <0x9cc>;
+ };
+ sadc: sadc@f1200000 {
+ compatible = "fh,fh-sadc";
+ reg = <0xf1200000 0x1000>;
+ interrupts = <20>;
+ ref-vol = <1800>;
+ active-bit = <0xfff>;
+ };
+ efuse: efuse@0xf1600000 {
+ compatible = "fh,fh-efuse";
+ reg = <0xf1600000 0x1000>;
+ key_switch = "enable";
+ indep_power = "enable";
+ };
+ fh_perf: fh_perf@0xf0002018 {
+ compatible = "fh,fh-perf";
+ reg = <0xf0000000 0x4000>;
+ interrupts = < 5 >;
+
+ };
+ spi_bus0: spi@f0500000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0500000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <6>;
+ cs1_gpio = <55>;
+ dma_enable = "disable";
+ swap_support = "enable";
+ rx_hs_no = <4>;
+ tx_hs_no = <5>;
+ bus_no = <0>;
+ multi_wire_size = <2>;
+ clk_name = "spi0_clk";
+ rx_dma_channel = <0>;
+ tx_dma_channel = <1>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <28>;
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fh,m25p80";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ reg = <0x0 0>; //first value means which slave bind to the master. 0 means chip 0. 1 means chip 1
+ partition@0 {
+ reg = <0x0 0x40000>;
+ label = "bootstrap";
+ };
+ partition@40000 {
+ reg = <0x40000 0x10000>;
+ label = "uboot-env";
+ };
+ partition@50000 {
+ reg = <0x50000 0x30000>;
+ label = "uboot";
+ };
+ partition@80000 {
+ reg = <0x80000 0x400000>;
+ label = "kernel";
+ };
+ partition@480000 {
+ reg = <0x480000 0x80000>;
+ label = "rootfs";
+ };
+ partition@500000 {
+ reg = <0x500000 0x300000>;
+ label = "app";
+ };
+
+ };
+ spidev0: spi@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ spi_bus1: spi@f0600000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0600000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <14>;
+ cs1_gpio = <57>;
+ dma_enable = "disable";
+ swap_support = "disable";
+ rx_hs_no = <2>;
+ tx_hs_no = <3>;
+ bus_no = <1>;
+ clk_name = "spi1_clk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <21>;
+ spidev1: spi@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x0 0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev2: spi@2 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ fhdwi2s: i2s@f0900000 {
+ compatible = "fh,fh-dw_i2s";
+ reg = <0xf0900000 0x1000>;
+ interrupts = <25>;
+ clocks = <&i2s_clk>, <&ac_clk>;
+ clock-names = "i2s_clk", "acodec_mclk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ dma_master = <0>;
+ dma_rx_hs_num = <10>;
+ dma_tx_hs_num = <11>;
+ };
+
+ fhacw: acw@f0a00000 {
+ compatible = "fh,fh-acw";
+ reg = <0xf0a00000 0x1000>;
+ interrupts = <19>;
+ clocks = <&ac_clk>;
+ clock-names = "ac_clk";
+ rx_dma_channel = <4>;
+ tx_dma_channel = <5>;
+ dma_master = <0>;
+ dma_rx_hs_num = <0>;
+ dma_tx_hs_num = <1>;
+ };
+
+ pwm: pwm@f0400000{
+ compatible = "fh,fh-pwm";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <36>;
+ npwm = <14>;
+ };
+ serial0: serial@f0700000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0700000 0x1000>;
+ interrupts = <30>;
+ clock-frequency = <16666667>;
+ fifo-size = <32>;
+ };
+ serial1: serial@f0800000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0800000 0x1000>;
+ interrupts = <31>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ serial2: serial@f1300000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf1300000 0x1000>;
+ interrupts = <41>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ gmac0: gmac@e0600000 {
+ compatible = "fh,fh-gmac";
+ reg = <0xe0600000 0x2000>;
+ interrupts = <44>;
+ phyreset-gpio = <29>;
+ };
+ sdc0: sdc0@e2000000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2000000 0x4000>;
+ interrupts = <42>;
+ id = <0>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <0>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <0>;
+ };
+ sdc1: sdc1@e2200000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2200000 0x4000>;
+ interrupts = <43>;
+ id = <1>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <1>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <2>;
+ };
+ wdt: wdt@f0d00000{
+ compatible = "fh,fh-wdt";
+ reg = <0xf0d00000 0x1000>;
+ interrupts = <2>;
+ mode = <1>;
+ };
+ i2cbus0: i2c@f0200000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0200000 0x2000>;
+ interrupts = <11>;
+ };
+ i2cbus1: i2c@f0b00000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0b00000 0x2000>;
+ interrupts = <12>;
+ };
+ i2cbus2: i2c@0xF0100000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xF0100000 0x2000>;
+ interrupts = <46>;
+ };
+ clocks: src_clk@0xf0000000{
+ compatible = "fh,fh-clk";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf0000000 0x80>;
+ ranges;
+
+ osc_clk: mxtal@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_clk";
+ };
+
+ pll_ddr_rclk: pllddrr{
+ #clock-cells = <0>;
+ compatible = "fh pll-ddr-rclk";
+ reg = <0xf0000010 0x4>,<0xf0000018 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_ddr_rclk";
+ };
+ pll_cpu_pclk: pllcpup{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-pclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_pclk";
+ };
+ pll_cpu_rclk: pllcpur{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-rclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_rclk";
+ };
+ pll_sys_pclk: pllsysp{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-pclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_pclk";
+ };
+ pll_sys_rclk: pllsysr{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-rclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_rclk";
+ };
+ sysp_div12_clk: syspdiv12clk{
+ #clock-cells = <0>;
+ compatible = "fh sysp-div12-clk";
+ reg = <0xf0000038 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sysp_div12_clk";
+ };
+ ddr_clk: ddrclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ddr-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clocks = <&pll_ddr_rclk>;
+ clock-output-names = "ddr_clk";
+ };
+ arm_clk: armclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arm-clk";
+ reg = <0x0 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_pclk>;
+ clock-output-names = "arm_clk";
+ };
+ arc_clk: arcclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arc-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ gate = <0x4000000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_rclk>;
+ clock-output-names = "arc_clk";
+ };
+ ahb_clk: ahbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ahb-clk";
+ reg = <0xf0000024 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ div = <0xf0000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_sys_pclk>;
+ clock-output-names = "ahb_clk";
+ };
+ isp_aclk: ispaclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispa-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00>;
+ gate = <0x1>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "isp_aclk";
+ };
+ ispb_aclk: ispbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispb-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "ispb_aclk";
+ };
+ vpu_clk: vpuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80000000>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "vpu_clk";
+ };
+ pix_clk: pixclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-pix-clk";
+ reg = <0xf000002c 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "pix_clk";
+ };
+ jpeg_clk: jpegclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-clk";
+ reg = <0xf000005c 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "jpeg_clk";
+ };
+ bgm_clk: bgmclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "bgm_clk";
+ };
+ jpeg_adapt_clk: jpegadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-adapt-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2>;
+ clocks = <&jpeg_clk>;
+ clock-output-names = "jpeg_adapt_clk";
+ };
+ spi0_clk: spi0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x80>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi0_clk";
+ };
+ sdc0_clk: sdc0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf00>;
+ gate = <0x200>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc0_clk";
+ };
+ spi2_clk: spi2clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi2-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000>;
+ gate = <0x2>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi2_clk";
+ };
+ spi1_clk: spi1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x100>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi1_clk";
+ };
+ sdc1_clk: sdc1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf000000>;
+ gate = <0x400>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc1_clk";
+ };
+ veu_clk: veuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ div = <0x7000000>;
+ gate = <0x10>;
+ mux = <0x4>;
+ clocks = <&pll_sys_pclk>,<&pll_sys_rclk>;
+ clock-output-names = "veu_clk";
+ };
+ veu_adapt_clk: veuadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-adapt-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clocks = <&veu_clk>;
+ clock-output-names = "veu_adapt_clk";
+ };
+ cis_clk_out: cisclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-cis-clk-out";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x800000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "cis_clk_out";
+ };
+ eth_clk: ethclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-eth-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ gate = <0x2000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "eth_clk";
+ };
+ eth_rmii_clk: ethrmiiclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ethrmii-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "eth_rmii_clk";
+ };
+ i2c0_clk: i2c0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f0000>;
+ gate = <0x1000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c0_clk";
+ };
+
+ i2c1_clk: i2c1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x8000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c1_clk";
+ };
+ i2c2_clk: i2c2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x00000008>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c2_clk";
+ };
+
+ uart0_clk: uart0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f>;
+ gate = <0x2000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart0_clk";
+ };
+
+ uart1_clk: uart1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f00>;
+ gate = <0x4000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart1_clk";
+ };
+ uart2_clk: uart2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f>;
+ gate = <0x8000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart2_clk";
+ };
+ pwm_clk: pwmclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pwm-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x10000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pwm_clk";
+ };
+ efuse_clk: efuseclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-efuse-clk";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x200000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "efuse_clk";
+ };
+ pts_clk: ptsclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pts-clk";
+ reg = <0xf000002c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1ff>;
+ gate = <0x80000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pts_clk";
+ };
+ tmr0_clk: tmr0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-tmr0-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x20000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "tmr0_clk";
+ };
+
+ sadc_clk: sadcclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sadc-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f0000>;
+ gate = <0x4000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "sadc_clk";
+ };
+ gpio0_dbclk: gpio0dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff>;
+ gate = <0x8000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio0_dbclk";
+ };
+ gpio1_dbclk: gpio1dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff0000>;
+ gate = <0x80000000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio1_dbclk";
+ };
+ wdt_clk: wdtclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-wdt-clk";
+ reg = <0xf0000038 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xff00>;
+ gate = <0x8000000>;
+ clocks = <&ahb_clk>;
+ clock-output-names = "wdt_clk";
+ };
+ ac_clk: acclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ac-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f>;
+ gate = <0x800>;
+ clocks = <&osc_clk>;
+ clock-output-names = "ac_clk";
+ };
+ i2s_clk: i2sclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-i2s-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x1000000>;
+ clocks = <&ac_clk>;
+ clock-output-names = "i2s_clk";
+ };
+ mipi_dphy_clk: mipidphyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-dphy-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x100000>;
+ clock-output-names = "mipi_dphy_clk";
+ };
+ mipi_wrap_gate: mipiwrapclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-wrap-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "mipi_wrap_gate";
+ };
+ rtc_hclk_gate: rtchclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-rtc-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "rtc_hclk_gate";
+ };
+ emac_hclk_gate: emachclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-emac-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "emac_hclk_gate";
+ };
+ usb_clk: usbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-usb-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "usb_clk";
+ };
+ aes_hclk_gate: aeshclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-aes-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80>;
+ clock-output-names = "aes_hclk_gate";
+ };
+ ephy_clk_gate: ephyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ephy-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1>;
+ clock-output-names = "ephy_clk_gate";
+ };
+ sdc0_clk8x_gate: sdc08xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc08x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clock-output-names = "sdc0_clk8x_gate";
+ };
+ sdc1_clk8x_gate: sdc18xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc18x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x8>;
+ clock-output-names = "sdc1_clk8x_gate";
+ };
+ mipic_pclk_gate: mipicpclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipic-pclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10>;
+ clock-output-names = "mipic_pclk_gate";
+ };
+ gpio0_pclk_gate: gpio0pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x4000>;
+ clock-output-names = "gpio0_pclk_gate";
+ };
+ gpio1_pclk_gate: gpio1pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "gpio1_pclk_gate";
+ };
+ isp_hclk_gate: isphclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-isp-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "isp_hclk_gate";
+ };
+ veu_hclk_gate: veuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "veu_hclk_gate";
+ };
+ bgm_hclk_gate: bgmhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clock-output-names = "bgm_hclk_gate";
+ };
+ adapt_hclk_gate: adapthclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-adapt-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x8000000>;
+ clock-output-names = "adapt_hclk_gate";
+ };
+ jpg_hclk_gate: jpghclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "jpg_hclk_gate";
+ };
+ jpg_adapt_gate: jpgadaptclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-adapt-clk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "jpg_adapt_gate";
+ };
+ vpu_hclk_gate: vpuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "vpu_hclk_gate";
+ };
+ sdc0_clk_sample: sdc0clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf0000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_sample";
+ };
+ sdc0_clk_drv: sdc0clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_drv";
+ };
+
+ sdc1_clk_sample: sdc1clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_sample";
+ };
+
+ sdc1_clk_drv: sdc1clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf000>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_drv";
+ };
+ };
+ };
+
+ usb_otg@e0700000 {
+ compatible = "fh_usb";
+ reg = <0xe0700000 100000>;
+ interrupts = <39>;
+ clocks = <&usb_clk>;
+ dr_mode = "host";
+ vbus_pwren = <47>;
+ clock-names = "otg";
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
+ };
+
+ usb2_phy: usbphy {
+ compatible = "fh,fh-usb2-phy";
+ #phy-cells = <0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/fh8856v210_pinctrl.dtsi b/arch/arm/boot/dts/fh8856v210_pinctrl.dtsi
new file mode 100644
index 00000000..cc0129ca
--- /dev/null
+++ b/arch/arm/boot/dts/fh8856v210_pinctrl.dtsi
@@ -0,0 +1,2386 @@
+/*
+ * Copyright (C) 2020 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ #define PUPD_NONE (0)
+ #define PUPD_UP (1)
+ #define PUPD_DOWN (2)
+*/
+
+/ {
+ pinctrl: pinctrl@f0000080 {
+ compatible = "fh,fh-pinctrl";
+ reg = <0xf0000080 0x104>;
+ pad-num = <65>;
+ max-mux = <9>;
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_ETH
+ &pinctrl_I2C0
+ &pinctrl_PWM2
+ &pinctrl_PWM3
+ &pinctrl_PWM4
+ &pinctrl_PWM5
+ &pinctrl_PWM6
+ &pinctrl_PWM7
+ &pinctrl_PWM8
+ &pinctrl_PWM9
+ &pinctrl_SADC_XAIN0
+ &pinctrl_SADC_XAIN1
+ &pinctrl_SD0_NO_WP
+ &pinctrl_SENSOR_CLK
+ &pinctrl_SSI0_4BIT
+ &pinctrl_UART0
+ &pinctrl_UART1
+ &pinctrl_GPIO4
+ &pinctrl_GPIO13
+ &pinctrl_GPIO30
+ &pinctrl_GPIO31
+ &pinctrl_GPIO32
+ &pinctrl_GPIO43
+ &pinctrl_GPIO44
+ &pinctrl_GPIO47
+
+ &pinctrl_GPIO11
+ &pinctrl_GPIO14
+ &pinctrl_GPIO15
+ &pinctrl_GPIO16
+ &pinctrl_GPIO24
+ &pinctrl_GPIO25
+ &pinctrl_GPIO45
+ &pinctrl_GPIO46
+ &pinctrl_GPIO48
+ &pinctrl_GPIO49
+ &pinctrl_GPIO50
+ &pinctrl_GPIO51
+ &pinctrl_GPIO52
+ &pinctrl_GPIO53
+ &pinctrl_GPIO54
+ &pinctrl_GPIO55
+ &pinctrl_GPIO56
+ &pinctrl_GPIO57
+ &pinctrl_GPIO58
+ &pinctrl_GPIO59
+ &pinctrl_GPIO60
+ &pinctrl_GPIO61
+ &pinctrl_GPIO62
+ &pinctrl_GPIO63
+ >;
+ pinctrl_groups {
+ pinctrl_ACI2S: ACI2S {
+ fh,pins = <
+ &mux_AC_I2S_CLK 0
+ &mux_AC_I2S_DI 0
+ &mux_AC_I2S_DO 0
+ &mux_AC_I2S_WS 0
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_AC_MCLK: AC_MCLK {
+ fh,pins = <
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_ARCJTAG: ARCJTAG {
+ fh,pins = <
+ &mux_ARC_JTAG_TCK 0
+ &mux_ARC_JTAG_TDI 0
+ &mux_ARC_JTAG_TDO 0
+ &mux_ARC_JTAG_TMS 0
+ &mux_ARC_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_ARMJTAG: ARMJTAG {
+ fh,pins = <
+ &mux_ARM_JTAG_TCK 0
+ &mux_ARM_JTAG_TDI 0
+ &mux_ARM_JTAG_TDO 0
+ &mux_ARM_JTAG_TMS 0
+ &mux_ARM_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_DWI2S: DWI2S {
+ fh,pins = <
+ &mux_DW_I2S_CLK 0
+ &mux_DW_I2S_DI 0
+ &mux_DW_I2S_DO 0
+ &mux_DW_I2S_WS 0
+ >;
+ };
+ pinctrl_ETH: ETH {
+ fh,pins = <
+ &mux_ETH_LINK_ACT 1
+ &mux_ETH_LINK_STA 1
+ >;
+ };
+ pinctrl_I2C0: I2C0 {
+ fh,pins = <
+ &mux_I2C0_SCL 0
+ &mux_I2C0_SDA 0
+ >;
+ };
+ pinctrl_I2C1: I2C1 {
+ fh,pins = <
+ &mux_I2C1_SCL 2
+ &mux_I2C1_SDA 2
+ >;
+ };
+ pinctrl_I2C2: I2C2 {
+ fh,pins = <
+ &mux_I2C2_SCL 1
+ &mux_I2C2_SDA 1
+ >;
+ };
+ pinctrl_PAEJTAG: PAEJTAG {
+ fh,pins = <
+ &mux_PAE_JTAG_TCK 0
+ &mux_PAE_JTAG_TDI 0
+ &mux_PAE_JTAG_TDO 0
+ &mux_PAE_JTAG_TMS 0
+ &mux_PAE_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_PWM0: PWM0 {
+ fh,pins = <
+ &mux_PWM0 0
+ >;
+ };
+ pinctrl_PWM1: PWM1 {
+ fh,pins = <
+ &mux_PWM1 0
+ >;
+ };
+ pinctrl_PWM10: PWM10 {
+ fh,pins = <
+ &mux_PWM10 0
+ >;
+ };
+ pinctrl_PWM11: PWM11 {
+ fh,pins = <
+ &mux_PWM11 0
+ >;
+ };
+ pinctrl_PWM2: PWM2 {
+ fh,pins = <
+ &mux_PWM2 0
+ >;
+ };
+ pinctrl_PWM3: PWM3 {
+ fh,pins = <
+ &mux_PWM3 0
+ >;
+ };
+ pinctrl_PWM4: PWM4 {
+ fh,pins = <
+ &mux_PWM4 0
+ >;
+ };
+ pinctrl_PWM5: PWM5 {
+ fh,pins = <
+ &mux_PWM5 0
+ >;
+ };
+ pinctrl_PWM6: PWM6 {
+ fh,pins = <
+ &mux_PWM6 1
+ >;
+ };
+ pinctrl_PWM7: PWM7 {
+ fh,pins = <
+ &mux_PWM7 1
+ >;
+ };
+ pinctrl_PWM8: PWM8 {
+ fh,pins = <
+ &mux_PWM8 1
+ >;
+ };
+ pinctrl_PWM9: PWM9 {
+ fh,pins = <
+ &mux_PWM9 1
+ >;
+ };
+ pinctrl_RMII: RMII {
+ fh,pins = <
+ &mux_MAC_MDC 1
+ &mux_MAC_MDIO 1
+ &mux_MAC_REF_CLK 0
+ &mux_MAC_RMII_CLK 0
+ &mux_MAC_RXDV 0
+ &mux_MAC_RXD_0 0
+ &mux_MAC_RXD_1 0
+ &mux_MAC_TXD_0 0
+ &mux_MAC_TXD_1 0
+ &mux_MAC_TXEN 0
+ >;
+ };
+ pinctrl_RTC: RTC {
+ fh,pins = <
+ &mux_RTC_CLK 0
+ >;
+ };
+ pinctrl_SADC_XAIN0: SADC_XAIN0 {
+ fh,pins = <
+ &mux_SADC_XAIN0 0
+ >;
+ };
+ pinctrl_SADC_XAIN1: SADC_XAIN1 {
+ fh,pins = <
+ &mux_SADC_XAIN1 0
+ >;
+ };
+ pinctrl_SADC_XAIN2: SADC_XAIN2 {
+ fh,pins = <
+ &mux_SADC_XAIN2 0
+ >;
+ };
+ pinctrl_SADC_XAIN3: SADC_XAIN3 {
+ fh,pins = <
+ &mux_SADC_XAIN3 0
+ >;
+ };
+ pinctrl_SD0: SD0 {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_1BIT_NO_WP: SD0_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ >;
+ };
+ pinctrl_SD0_NO_WP: SD0_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_WIFI: SD0_WIFI {
+ fh,pins = <
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD1: SD1 {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_1BIT_NO_WP: SD1_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ >;
+ };
+ pinctrl_SD1_NO_WP: SD1_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 0
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SD1_WIFI: SD1_WIFI {
+ fh,pins = <
+ &mux_SD1_CLK 0
+ &mux_SD1_CMD_RSP 0
+ &mux_SD1_DATA_0 0
+ &mux_SD1_DATA_1 0
+ &mux_SD1_DATA_2 0
+ &mux_SD1_DATA_3 0
+ >;
+ };
+ pinctrl_SENSOR_CLK: SENSOR_CLK {
+ fh,pins = <
+ &mux_SENSOR_CLK 0
+ >;
+ };
+ pinctrl_SSI0: SSI0 {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI0_4BIT: SSI0_4BIT {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_D2 0
+ &mux_SSI0_D3 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI1: SSI1 {
+ fh,pins = <
+ &mux_GPIO14 0
+ &mux_SSI1_CLK 2
+ &mux_SSI1_RXD 2
+ &mux_SSI1_TXD 2
+ >;
+ };
+ pinctrl_SSI2: SSI2 {
+ fh,pins = <
+ &mux_SSI2_CLK 1
+ &mux_SSI2_CSN_0 1
+ &mux_SSI2_RXD 1
+ &mux_SSI2_TXD 1
+ >;
+ };
+ pinctrl_UART0: UART0 {
+ fh,pins = <
+ &mux_UART0_RX 0
+ &mux_UART0_TX 0
+ >;
+ };
+ pinctrl_UART1: UART1 {
+ fh,pins = <
+ &mux_UART1_RX 0
+ &mux_UART1_TX 0
+ >;
+ };
+ pinctrl_UART2: UART2 {
+ fh,pins = <
+ &mux_UART2_RX 0
+ &mux_UART2_TX 0
+ >;
+ };
+ pinctrl_USB: USB {
+ fh,pins = <
+ &mux_USB_PWREN 0
+ >;
+ };
+ pinctrl_GPIO0: GPIO0 {
+ fh,pins = <
+ &mux_GPIO0 0
+ >;
+ };
+ pinctrl_GPIO1: GPIO1 {
+ fh,pins = <
+ &mux_GPIO1 0
+ >;
+ };
+ pinctrl_GPIO2: GPIO2 {
+ fh,pins = <
+ &mux_GPIO2 0
+ >;
+ };
+ pinctrl_GPIO3: GPIO3 {
+ fh,pins = <
+ &mux_GPIO3 0
+ >;
+ };
+ pinctrl_GPIO4: GPIO4 {
+ fh,pins = <
+ &mux_GPIO4 0
+ >;
+ };
+ pinctrl_GPIO5: GPIO5 {
+ fh,pins = <
+ &mux_GPIO5 0
+ >;
+ };
+ pinctrl_GPIO6: GPIO6 {
+ fh,pins = <
+ &mux_GPIO6 0
+ >;
+ };
+ pinctrl_GPIO7: GPIO7 {
+ fh,pins = <
+ &mux_GPIO7 0
+ >;
+ };
+ pinctrl_GPIO8: GPIO8 {
+ fh,pins = <
+ &mux_GPIO8 0
+ >;
+ };
+ pinctrl_GPIO9: GPIO9 {
+ fh,pins = <
+ &mux_GPIO9 0
+ >;
+ };
+ pinctrl_GPIO10: GPIO10 {
+ fh,pins = <
+ &mux_GPIO10 0
+ >;
+ };
+ pinctrl_GPIO11: GPIO11 {
+ fh,pins = <
+ &mux_GPIO11 0
+ >;
+ };
+ pinctrl_GPIO12: GPIO12 {
+ fh,pins = <
+ &mux_GPIO12 0
+ >;
+ };
+ pinctrl_GPIO13: GPIO13 {
+ fh,pins = <
+ &mux_GPIO13 0
+ >;
+ };
+ pinctrl_GPIO14: GPIO14 {
+ fh,pins = <
+ &mux_GPIO14 0
+ >;
+ };
+ pinctrl_GPIO15: GPIO15 {
+ fh,pins = <
+ &mux_GPIO15 0
+ >;
+ };
+ pinctrl_GPIO16: GPIO16 {
+ fh,pins = <
+ &mux_GPIO16 0
+ >;
+ };
+ pinctrl_GPIO17: GPIO17 {
+ fh,pins = <
+ &mux_GPIO17 0
+ >;
+ };
+ pinctrl_GPIO18: GPIO18 {
+ fh,pins = <
+ &mux_GPIO18 0
+ >;
+ };
+ pinctrl_GPIO19: GPIO19 {
+ fh,pins = <
+ &mux_GPIO19 0
+ >;
+ };
+ pinctrl_GPIO20: GPIO20 {
+ fh,pins = <
+ &mux_GPIO20 0
+ >;
+ };
+ pinctrl_GPIO21: GPIO21 {
+ fh,pins = <
+ &mux_GPIO21 0
+ >;
+ };
+ pinctrl_GPIO22: GPIO22 {
+ fh,pins = <
+ &mux_GPIO22 0
+ >;
+ };
+ pinctrl_GPIO23: GPIO23 {
+ fh,pins = <
+ &mux_GPIO23 0
+ >;
+ };
+ pinctrl_GPIO24: GPIO24 {
+ fh,pins = <
+ &mux_GPIO24 0
+ >;
+ };
+ pinctrl_GPIO25: GPIO25 {
+ fh,pins = <
+ &mux_GPIO25 0
+ >;
+ };
+ pinctrl_GPIO26: GPIO26 {
+ fh,pins = <
+ &mux_GPIO26 0
+ >;
+ };
+ pinctrl_GPIO27: GPIO27 {
+ fh,pins = <
+ &mux_GPIO27 0
+ >;
+ };
+ pinctrl_GPIO28: GPIO28 {
+ fh,pins = <
+ &mux_GPIO28 0
+ >;
+ };
+ pinctrl_GPIO29: GPIO29 {
+ fh,pins = <
+ &mux_GPIO29 0
+ >;
+ };
+ pinctrl_GPIO30: GPIO30 {
+ fh,pins = <
+ &mux_GPIO30 0
+ >;
+ };
+ pinctrl_GPIO31: GPIO31 {
+ fh,pins = <
+ &mux_GPIO31 0
+ >;
+ };
+ pinctrl_GPIO32: GPIO32 {
+ fh,pins = <
+ &mux_GPIO32 0
+ >;
+ };
+ pinctrl_GPIO33: GPIO33 {
+ fh,pins = <
+ &mux_GPIO33 0
+ >;
+ };
+ pinctrl_GPIO34: GPIO34 {
+ fh,pins = <
+ &mux_GPIO34 0
+ >;
+ };
+ pinctrl_GPIO35: GPIO35 {
+ fh,pins = <
+ &mux_GPIO35 0
+ >;
+ };
+ pinctrl_GPIO36: GPIO36 {
+ fh,pins = <
+ &mux_GPIO36 0
+ >;
+ };
+ pinctrl_GPIO37: GPIO37 {
+ fh,pins = <
+ &mux_GPIO37 0
+ >;
+ };
+ pinctrl_GPIO38: GPIO38 {
+ fh,pins = <
+ &mux_GPIO38 0
+ >;
+ };
+ pinctrl_GPIO39: GPIO39 {
+ fh,pins = <
+ &mux_GPIO39 0
+ >;
+ };
+ pinctrl_GPIO40: GPIO40 {
+ fh,pins = <
+ &mux_GPIO40 0
+ >;
+ };
+ pinctrl_GPIO41: GPIO41 {
+ fh,pins = <
+ &mux_GPIO41 0
+ >;
+ };
+ pinctrl_GPIO42: GPIO42 {
+ fh,pins = <
+ &mux_GPIO42 0
+ >;
+ };
+ pinctrl_GPIO43: GPIO43 {
+ fh,pins = <
+ &mux_GPIO43 0
+ >;
+ };
+ pinctrl_GPIO44: GPIO44 {
+ fh,pins = <
+ &mux_GPIO44 0
+ >;
+ };
+ pinctrl_GPIO45: GPIO45 {
+ fh,pins = <
+ &mux_GPIO45 0
+ >;
+ };
+ pinctrl_GPIO46: GPIO46 {
+ fh,pins = <
+ &mux_GPIO46 0
+ >;
+ };
+ pinctrl_GPIO47: GPIO47 {
+ fh,pins = <
+ &mux_GPIO47 0
+ >;
+ };
+ pinctrl_GPIO48: GPIO48 {
+ fh,pins = <
+ &mux_GPIO48 0
+ >;
+ };
+ pinctrl_GPIO49: GPIO49 {
+ fh,pins = <
+ &mux_GPIO49 0
+ >;
+ };
+ pinctrl_GPIO50: GPIO50 {
+ fh,pins = <
+ &mux_GPIO50 0
+ >;
+ };
+ pinctrl_GPIO51: GPIO51 {
+ fh,pins = <
+ &mux_GPIO51 0
+ >;
+ };
+ pinctrl_GPIO52: GPIO52 {
+ fh,pins = <
+ &mux_GPIO52 0
+ >;
+ };
+ pinctrl_GPIO53: GPIO53 {
+ fh,pins = <
+ &mux_GPIO53 0
+ >;
+ };
+ pinctrl_GPIO54: GPIO54 {
+ fh,pins = <
+ &mux_GPIO54 0
+ >;
+ };
+ pinctrl_GPIO55: GPIO55 {
+ fh,pins = <
+ &mux_GPIO55 0
+ >;
+ };
+ pinctrl_GPIO56: GPIO56 {
+ fh,pins = <
+ &mux_GPIO56 0
+ >;
+ };
+ pinctrl_GPIO57: GPIO57 {
+ fh,pins = <
+ &mux_GPIO57 0
+ >;
+ };
+ pinctrl_GPIO58: GPIO58 {
+ fh,pins = <
+ &mux_GPIO58 0
+ >;
+ };
+ pinctrl_GPIO59: GPIO59 {
+ fh,pins = <
+ &mux_GPIO59 0
+ >;
+ };
+ pinctrl_GPIO60: GPIO60 {
+ fh,pins = <
+ &mux_GPIO60 0
+ >;
+ };
+ pinctrl_GPIO61: GPIO61 {
+ fh,pins = <
+ &mux_GPIO61 0
+ >;
+ };
+ pinctrl_GPIO62: GPIO62 {
+ fh,pins = <
+ &mux_GPIO62 0
+ >;
+ };
+ pinctrl_GPIO63: GPIO63 {
+ fh,pins = <
+ &mux_GPIO63 0
+ >;
+ };
+ pinctrl_SD1_EMMC: SD1_EMMC {
+ fh,pins = <
+ &mux_SD1_CD 3
+ &mux_SD1_CLK 3
+ &mux_SD1_CMD_RSP 3
+ &mux_SD1_DATA_0 3
+ &mux_SD1_DATA_1 3
+ &mux_SD1_DATA_2 3
+ &mux_SD1_DATA_3 3
+ >;
+ };
+ };
+ pinmux: pinmux {
+ compatible = "fh,fh-pinmux";
+ #list-cells = <1>;
+ mux_AC_I2S_CLK: AC_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_AC_I2S_DI: AC_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_AC_I2S_DO: AC_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_AC_I2S_WS: AC_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_AC_MCLK: AC_MCLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+
+ mux_ARC_JTAG_TCK: ARC_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_ARC_JTAG_TDI: ARC_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_ARC_JTAG_TDO: ARC_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_ARC_JTAG_TMS: ARC_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_ARC_JTAG_TRSTN: ARC_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_ARM_JTAG_TCK: ARM_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_ARM_JTAG_TDI: ARM_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_ARM_JTAG_TDO: ARM_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_ARM_JTAG_TMS: ARM_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_ARM_JTAG_TRSTN: ARM_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+
+ mux_DW_I2S_CLK: DW_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_DW_I2S_DI: DW_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_DW_I2S_DO: DW_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_DW_I2S_WS: DW_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+
+ mux_ETH_LINK_ACT: ETH_LINK_ACT {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad1
+ &pad63
+ >;
+ };
+ mux_ETH_LINK_SPD: ETH_LINK_SPD {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+ mux_ETH_LINK_STA: ETH_LINK_STA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+
+ mux_I2C0_SCL: I2C0_SCL {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_I2C0_SDA: I2C0_SDA {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+
+ mux_I2C1_SCL: I2C1_SCL {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad11
+ &pad30
+ &pad46
+ >;
+ };
+ mux_I2C1_SDA: I2C1_SDA {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad12
+ &pad31
+ &pad47
+ >;
+ };
+
+ mux_I2C2_SCL: I2C2_SCL {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad16
+ &pad57
+ >;
+ };
+ mux_I2C2_SDA: I2C2_SDA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad17
+ &pad58
+ >;
+ };
+
+ mux_MAC_MDC: MAC_MDC {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad28
+ &pad63
+ >;
+ };
+ mux_MAC_MDIO: MAC_MDIO {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <0>;
+ fh,pads = <
+ &pad29
+ &pad64
+ >;
+ };
+ mux_MAC_REF_CLK: MAC_REF_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad21
+ >;
+ };
+ mux_MAC_RMII_CLK: MAC_RMII_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_MAC_RXDV: MAC_RXDV {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_MAC_RXD_0: MAC_RXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_MAC_RXD_1: MAC_RXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_MAC_TXD_0: MAC_TXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_MAC_TXD_1: MAC_TXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_MAC_TXEN: MAC_TXEN {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+
+ mux_PAE_JTAG_TCK: PAE_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_PAE_JTAG_TDI: PAE_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_PAE_JTAG_TDO: PAE_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_PAE_JTAG_TMS: PAE_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_PAE_JTAG_TRSTN: PAE_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_PWM0: PWM0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_PWM1: PWM1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_PWM10: PWM10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_PWM11: PWM11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_PWM2: PWM2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ &pad18
+ &pad20
+ >;
+ };
+ mux_PWM3: PWM3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ &pad19
+ &pad22
+ >;
+ };
+ mux_PWM4: PWM4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad23
+ >;
+ };
+ mux_PWM5: PWM5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad24
+ >;
+ };
+ mux_PWM6: PWM6 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad25
+ &pad37
+ >;
+ };
+ mux_PWM7: PWM7 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad26
+ &pad38
+ >;
+ };
+ mux_PWM8: PWM8 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad27
+ &pad39
+ >;
+ };
+ mux_PWM9: PWM9 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad28
+ &pad40
+ >;
+ };
+
+ mux_RTC_CLK: RTC_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+
+ mux_SADC_XAIN0: SADC_XAIN0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_SADC_XAIN1: SADC_XAIN1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_SADC_XAIN2: SADC_XAIN2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_SADC_XAIN3: SADC_XAIN3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+
+ mux_SD0_CD: SD0_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_SD0_CLK: SD0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <3>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_SD0_CMD_RSP: SD0_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_SD0_DATA_0: SD0_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_SD0_DATA_1: SD0_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_SD0_DATA_2: SD0_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_SD0_DATA_3: SD0_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+
+ mux_SD1_CD: SD1_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad10
+ &pad22
+ &pad31
+ &pad41
+ &pad63
+ >;
+ };
+ mux_SD1_CLK: SD1_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <3>;
+ fh,pads = <
+ &pad9
+ &pad20
+ &pad30
+ &pad42
+ >;
+ };
+ mux_SD1_CMD_RSP: SD1_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad23
+ &pad32
+ &pad43
+ >;
+ };
+ mux_SD1_DATA_0: SD1_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad12
+ &pad24
+ &pad33
+ &pad44
+ >;
+ };
+ mux_SD1_DATA_1: SD1_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad25
+ &pad34
+ &pad45
+ >;
+ };
+ mux_SD1_DATA_2: SD1_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad26
+ &pad35
+ &pad46
+ >;
+ };
+ mux_SD1_DATA_3: SD1_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad15
+ &pad27
+ &pad36
+ &pad47
+ >;
+ };
+
+ mux_SENSOR_CLK: SENSOR_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+
+ mux_SSI0_CLK: SSI0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_SSI0_D2: SSI0_D2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_SSI0_D3: SSI0_D3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_SSI0_RXD: SSI0_RXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_SSI0_TXD: SSI0_TXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+
+ mux_SSI1_CLK: SSI1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad37
+ &pad48
+ &pad53
+ >;
+ };
+ mux_SSI1_RXD: SSI1_RXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad40
+ &pad51
+ &pad55
+ >;
+ };
+ mux_SSI1_TXD: SSI1_TXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad39
+ &pad50
+ &pad54
+ >;
+ };
+
+ mux_SSI2_CLK: SSI2_CLK {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad37
+ &pad48
+ >;
+ };
+ mux_SSI2_CSN_0: SSI2_CSN_0 {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad38
+ &pad49
+ >;
+ };
+ mux_SSI2_RXD: SSI2_RXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad40
+ &pad51
+ >;
+ };
+ mux_SSI2_TXD: SSI2_TXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad39
+ &pad50
+ >;
+ };
+
+ mux_UART0_RX: UART0_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_UART0_TX: UART0_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+
+ mux_UART1_RX: UART1_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ &pad33
+ &pad47
+ >;
+ };
+ mux_UART1_TX: UART1_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ &pad32
+ &pad46
+ >;
+ };
+
+ mux_UART2_RX: UART2_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad17
+ &pad35
+ &pad58
+ >;
+ };
+ mux_UART2_TX: UART2_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad16
+ &pad34
+ &pad57
+ >;
+ };
+
+ mux_USB_PWREN: USB_PWREN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ &pad41
+ >;
+ };
+
+ mux_GPIO0: GPIO0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_GPIO1: GPIO1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_GPIO2: GPIO2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_GPIO3: GPIO3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_GPIO4: GPIO4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_GPIO5: GPIO5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_GPIO6: GPIO6 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad43
+ >;
+ };
+ mux_GPIO7: GPIO7 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+ mux_GPIO8: GPIO8 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_GPIO9: GPIO9 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_GPIO10: GPIO10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_GPIO11: GPIO11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad48
+ >;
+ };
+ mux_GPIO12: GPIO12 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+ mux_GPIO13: GPIO13 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad8
+ >;
+ };
+ mux_GPIO14: GPIO14 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad49
+ >;
+ };
+ mux_GPIO15: GPIO15 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad50
+ >;
+ };
+ mux_GPIO16: GPIO16 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad51
+ >;
+ };
+ mux_GPIO17: GPIO17 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_GPIO18: GPIO18 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_GPIO19: GPIO19 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_GPIO20: GPIO20 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_GPIO21: GPIO21 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_GPIO22: GPIO22 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_GPIO23: GPIO23 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+ mux_GPIO24: GPIO24 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_GPIO25: GPIO25 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+ mux_GPIO26: GPIO26 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_GPIO27: GPIO27 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_GPIO28: GPIO28 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_GPIO29: GPIO29 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_GPIO30: GPIO30 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad0
+ >;
+ };
+ mux_GPIO31: GPIO31 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad1
+ >;
+ };
+ mux_GPIO32: GPIO32 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad2
+ >;
+ };
+ mux_GPIO33: GPIO33 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+ mux_GPIO34: GPIO34 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_GPIO35: GPIO35 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_GPIO36: GPIO36 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+ mux_GPIO37: GPIO37 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ >;
+ };
+ mux_GPIO38: GPIO38 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ >;
+ };
+ mux_GPIO39: GPIO39 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ >;
+ };
+ mux_GPIO40: GPIO40 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ >;
+ };
+ mux_GPIO41: GPIO41 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ >;
+ };
+ mux_GPIO42: GPIO42 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ >;
+ };
+ mux_GPIO43: GPIO43 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_GPIO44: GPIO44 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_GPIO45: GPIO45 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad18
+ >;
+ };
+ mux_GPIO46: GPIO46 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad19
+ >;
+ };
+ mux_GPIO47: GPIO47 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ >;
+ };
+ mux_GPIO48: GPIO48 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_GPIO49: GPIO49 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_GPIO50: GPIO50 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_GPIO51: GPIO51 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+ mux_GPIO52: GPIO52 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_GPIO53: GPIO53 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_GPIO54: GPIO54 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_GPIO55: GPIO55 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad28
+ >;
+ };
+ mux_GPIO56: GPIO56 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad29
+ >;
+ };
+ mux_GPIO57: GPIO57 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad30
+ >;
+ };
+ mux_GPIO58: GPIO58 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad31
+ >;
+ };
+ mux_GPIO59: GPIO59 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad32
+ >;
+ };
+ mux_GPIO60: GPIO60 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad33
+ >;
+ };
+ mux_GPIO61: GPIO61 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad34
+ >;
+ };
+ mux_GPIO62: GPIO62 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad35
+ >;
+ };
+ mux_GPIO63: GPIO63 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad36
+ >;
+ };
+ };
+ pinpad: pinpad {
+ compatible = "fh,fh-pinpad";
+ pad0: PAD_BOOT_MODE_CFG {
+ index = <0>;
+ funcs = "GPIO30";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad1: PAD_BOOT_SEL1_CFG {
+ index = <1>;
+ funcs = "GPIO31", "ETH_LINK_ACT";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad2: PAD_BOOT_SEL0_CFG {
+ index = <2>;
+ funcs = "GPIO32", "ETH_LINK_STA", "ETH_LINK_SPD";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad3: PAD_UART0_TX_CFG {
+ index = <3>;
+ funcs = "UART0_TX", "GPIO33";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad4: PAD_UART0_RX_CFG {
+ index = <4>;
+ funcs = "UART0_RX", "GPIO34";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad5: PAD_I2C0_SCL_CFG {
+ index = <5>;
+ funcs = "I2C0_SCL", "GPIO35";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad6: PAD_I2C0_SDA_CFG {
+ index = <6>;
+ funcs = "I2C0_SDA", "GPIO36";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad7: PAD_SENSOR_CLK_CFG {
+ index = <7>;
+ funcs = "SENSOR_CLK", "GPIO12";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad8: PAD_SENSOR_RSTN_CFG {
+ index = <8>;
+ funcs = "GPIO13";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad9: PAD_UART1_TX_CFG {
+ index = <9>;
+ funcs = "UART1_TX", "GPIO39", "", "SD1_CLK", "", "",
+ "TEST_O_INT_RMII_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad10: PAD_UART1_RX_CFG {
+ index = <10>;
+ funcs = "UART1_RX", "GPIO40", "", "SD1_CD", "", "",
+ "TEST_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad11: PAD_I2C1_SCL_CFG {
+ index = <11>;
+ funcs = "I2C1_SCL", "GPIO37", "PWM2", "SD1_CMD_RSP", "",
+ "SSI1_CLK", "TEST_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad12: PAD_I2C1_SDA_CFG {
+ index = <12>;
+ funcs = "I2C1_SDA", "GPIO38", "PWM3", "SD1_DATA_0", "",
+ "SSI1_CSN_0", "TEST_INT_RMII_TXEN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad13: PAD_UART2_TX_CFG {
+ index = <13>;
+ funcs = "UART2_TX", "GPIO41", "PWM4", "SD1_DATA_1", "",
+ "SSI1_TXD", "TEST_O_INT_RMII_RXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad14: PAD_UART2_RX_CFG {
+ index = <14>;
+ funcs = "UART2_RX", "GPIO42", "PWM5", "SD1_DATA_2", "",
+ "SSI1_RXD", "TEST_O_INT_RMII_RXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad15: PAD_USB_PWREN_CFG {
+ index = <15>;
+ funcs = "USB_PWREN", "GPIO47", "", "SD1_DATA_3", "", "",
+ "TEST_O_INT_RMII_CRSDV";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad16: PAD_PWM0_CFG {
+ index = <16>;
+ funcs = "PWM0", "GPIO43", "I2C2_SCL", "UART2_TX", "", "",
+ "TEST_O_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad17: PAD_PWM1_CFG {
+ index = <17>;
+ funcs = "PWM1", "GPIO44", "I2C2_SDA", "UART2_RX", "", "",
+ "TEST_O_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad18: PAD_PWM2_CFG {
+ index = <18>;
+ funcs = "PWM2", "GPIO45";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad19: PAD_PWM3_CFG {
+ index = <19>;
+ funcs = "PWM3", "GPIO46";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad20: PAD_MAC_RMII_CLK_CFG {
+ index = <20>;
+ funcs = "MAC_RMII_CLK", "GPIO48", "SD1_CLK", "PWM2";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad21: PAD_MAC_REF_CLK_CFG {
+ index = <21>;
+ funcs = "MAC_REF_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad22: PAD_MAC_TXD0_CFG {
+ index = <22>;
+ funcs = "MAC_TXD_0", "GPIO49", "SD1_CD", "PWM3";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad23: PAD_MAC_TXD1_CFG {
+ index = <23>;
+ funcs = "MAC_TXD_1", "GPIO50", "SD1_CMD_RSP", "PWM4";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad24: PAD_MAC_TXEN_CFG {
+ index = <24>;
+ funcs = "MAC_TXEN", "GPIO51", "SD1_DATA_0", "PWM5";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad25: PAD_MAC_RXD0_CFG {
+ index = <25>;
+ funcs = "MAC_RXD_0", "GPIO52", "SD1_DATA_1", "PWM6";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad26: PAD_MAC_RXD1_CFG {
+ index = <26>;
+ funcs = "MAC_RXD_1", "GPIO53", "SD1_DATA_2", "PWM7";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad27: PAD_MAC_RXDV_CFG {
+ index = <27>;
+ funcs = "MAC_RXDV", "GPIO54", "SD1_DATA_3", "PWM8";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad28: PAD_MAC_MDC_CFG {
+ index = <28>;
+ funcs = "MAC_MDC", "GPIO55", "", "PWM9";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad29: PAD_MAC_MDIO_CFG {
+ index = <29>;
+ funcs = "MAC_MDIO", "GPIO56";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad30: PAD_SD1_CLK_CFG {
+ index = <30>;
+ funcs = "SD1_CLK", "GPIO57", "I2C1_SCL";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad31: PAD_SD1_CD_CFG {
+ index = <31>;
+ funcs = "SD1_CD", "GPIO58", "I2C1_SDA";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad32: PAD_SD1_CMD_RSP_CFG {
+ index = <32>;
+ funcs = "SD1_CMD_RSP", "GPIO59", "UART1_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad33: PAD_SD1_DATA_0_CFG {
+ index = <33>;
+ funcs = "SD1_DATA_0", "GPIO60", "UART1_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad34: PAD_SD1_DATA_1_CFG {
+ index = <34>;
+ funcs = "SD1_DATA_1", "GPIO61", "UART2_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad35: PAD_SD1_DATA_2_CFG {
+ index = <35>;
+ funcs = "SD1_DATA_2", "GPIO62", "UART2_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad36: PAD_SD1_DATA_3_CFG {
+ index = <36>;
+ funcs = "SD1_DATA_3", "GPIO63";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad37: PAD_GPIO_0_CFG {
+ index = <37>;
+ funcs = "ARM_JTAG_TRSTN", "GPIO0", "AC_I2S_DO", "DW_I2S_DO",
+ "SSI1_CLK", "SSI2_CLK", "ACIP_ADDAT", "PWM6",
+ "TEST_O_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad38: PAD_GPIO_1_CFG {
+ index = <38>;
+ funcs = "ARM_JTAG_TDO", "GPIO1", "AC_I2S_DI", "DW_I2S_DI",
+ "SSI1_CSN_0", "SSI2_CSN_0", "ACIP_DADAT", "PWM7",
+ "TEST_O_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad39: PAD_GPIO_2_CFG {
+ index = <39>;
+ funcs = "ARM_JTAG_TDI", "GPIO2", "AC_I2S_CLK", "DW_I2S_CLK",
+ "SSI1_TXD", "SSI2_TXD", "ACIP_ADBCLK", "PWM8",
+ "TEST_O_INT_SMI_MDIO_O";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad40: PAD_GPIO_3_CFG {
+ index = <40>;
+ funcs = "ARM_JTAG_TCK", "GPIO3", "AC_I2S_WS", "DW_I2S_WS",
+ "SSI1_RXD", "SSI2_RXD", "ACIP_ADLRC", "PWM9",
+ "TEST_I_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad41: PAD_GPIO_4_CFG {
+ index = <41>;
+ funcs = "ARM_JTAG_TMS", "GPIO4", "AC_MCLK", "USB_PWREN",
+ "SD1_CD", "TEST_I_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad42: PAD_SSI0_CLK_CFG {
+ index = <42>;
+ funcs = "SSI0_CLK", "GPIO5", "", "", "SD1_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad43: PAD_SSI0_CSN_0_CFG {
+ index = <43>;
+ funcs = "SSI0_CSN_0", "GPIO6", "", "", "SD1_CMD_RSP";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad44: PAD_SSI0_TXD_CFG {
+ index = <44>;
+ funcs = "SSI0_TXD", "GPIO7", "", "", "SD1_DATA_0";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad45: PAD_SSI0_RXD_CFG {
+ index = <45>;
+ funcs = "SSI0_RXD", "GPIO8", "", "", "SD1_DATA_1";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad46: PAD_SSI0_D2_CFG {
+ index = <46>;
+ funcs = "SSI0_D2", "GPIO9", "UART1_TX", "I2C1_SCL",
+ "SD1_DATA_2";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad47: PAD_SSI0_D3_CFG {
+ index = <47>;
+ funcs = "SSI0_D3", "GPIO10", "UART1_RX", "I2C1_SDA",
+ "SD1_DATA_3";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad48: PAD_SSI1_CLK_CFG {
+ index = <48>;
+ funcs = "SSI1_CLK", "GPIO11", "SSI2_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad49: PAD_SSI1_CSN_0_CFG {
+ index = <49>;
+ funcs = "SSI1_CSN_0", "GPIO14", "SSI2_CSN_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad50: PAD_SSI1_TXD_CFG {
+ index = <50>;
+ funcs = "SSI1_TXD", "GPIO15", "SSI2_TXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad51: PAD_SSI1_RXD_CFG {
+ index = <51>;
+ funcs = "SSI1_RXD", "GPIO16", "SSI2_RXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad52: PAD_SD0_CD_CFG {
+ index = <52>;
+ funcs = "SD0_CD", "GPIO17", "", "ARC_JTAG_TRSTN",
+ "PAE_JTAG_TRSTN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad53: PAD_SD0_CLK_CFG {
+ index = <53>;
+ funcs = "SD0_CLK", "GPIO18", "SSI1_CLK", "ARC_JTAG_TDO",
+ "PAE_JTAG_TDO";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad54: PAD_SD0_CMD_RSP_CFG {
+ index = <54>;
+ funcs = "SD0_CMD_RSP", "GPIO19", "SSI1_TXD", "ARC_JTAG_TDI",
+ "PAE_JTAG_TDI";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad55: PAD_SD0_DATA_0_CFG {
+ index = <55>;
+ funcs = "SD0_DATA_0", "GPIO20", "SSI1_RXD", "ARC_JTAG_TCK",
+ "PAE_JTAG_TCK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad56: PAD_SD0_DATA_1_CFG {
+ index = <56>;
+ funcs = "SD0_DATA_1", "GPIO21", "SSI1_CSN_0", "ARC_JTAG_TMS",
+ "PAE_JTAG_TMS";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad57: PAD_SD0_DATA_2_CFG {
+ index = <57>;
+ funcs = "SD0_DATA_2", "GPIO22", "", "UART2_TX", "I2C2_SCL", "",
+ "ACIP_DABCLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad58: PAD_SD0_DATA_3_CFG {
+ index = <58>;
+ funcs = "SD0_DATA_3", "GPIO23", "SSI1_CSN_0", "UART2_RX",
+ "I2C2_SDA", "", "ACIP_DALRC";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad59: PAD_SADC_XAIN0_CFG {
+ index = <59>;
+ funcs = "SADC_XAIN0", "GPIO26";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad60: PAD_SADC_XAIN1_CFG {
+ index = <60>;
+ funcs = "SADC_XAIN1", "GPIO27";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad61: PAD_SADC_XAIN2_CFG {
+ index = <61>;
+ funcs = "SADC_XAIN2", "GPIO24";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad62: PAD_SADC_XAIN3_CFG {
+ index = <62>;
+ funcs = "SADC_XAIN3", "GPIO25";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad63: PAD_GPIO_28_CFG {
+ index = <63>;
+ funcs = "GPIO28", "", "ETH_LINK_ACT", "PWM10",
+ "USB_DBG_CLK", "SD1_CD", "TEST_O_INT_RMII_TXEN",
+ "MAC_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad64: PAD_GPIO_29_CFG {
+ index = <64>;
+ funcs = "GPIO29", "", "ETH_LINK_STA", "PWM11", "RTC_CLK",
+ "ETH_LINK_SPD", "TEST_O_INT_SMI_MDIO_OE",
+ "MAC_MDIO";
+ pupd = <0>;
+ ds = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/fh8858v200.dts b/arch/arm/boot/dts/fh8858v200.dts
new file mode 100644
index 00000000..35499672
--- /dev/null
+++ b/arch/arm/boot/dts/fh8858v200.dts
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2017 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+/include/ "fh8858v200_pinctrl.dtsi"
+/ {
+
+
+ model = "FULLHAN FH8858V200";
+ compatible = "fh,fh8858v200";
+ interrupt-parent = <&intc>;
+ aliases {
+ i2c0 = &i2cbus0;
+ i2c1 = &i2cbus1;
+ i2c2 = &i2cbus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ ttyS0 = &serial0;
+ ttyS1 = &serial1;
+ ttyS2 = &serial2;
+ };
+
+ cpus {
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,arm1176jzf-s";
+ };
+ };
+
+ chosen {
+ bootargs = "coherent_pool=2M";
+ };
+
+ intc: interrupt-controller@E0200000 {
+ compatible = "fh,fh-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xE0200000 0x1000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pmu@f0000000 {
+ compatible = "fh,fh-pmu";
+ reg = <0xf0000000 0x2100>;
+ SWRST_MAIN_CTRL = <0x40>;
+ };
+ timer0: timer@f0c00000 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00000 0x14>;
+ };
+
+ timer1: timer@f0c00014 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00014 0x14>;
+ };
+
+ gpio0: gpio@f0300000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf0300000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <26>;
+ id = <0>;
+ ngpio = <32>;
+ base = <0>;
+ };
+
+ gpio1: gpio@f4000000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf4000000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <40>;
+ id = <1>;
+ ngpio = <32>;
+ base = <32>;
+ };
+
+ fhdma0: dma@e0300000 {
+ compatible = "fh,fh-axi-dmac";
+ reg = <0xe0300000 0x1000>;
+ interrupts = <23>;
+ chan_allocation_order = <0>;
+ chan_priority = <1>;
+ block_size = <0x800>;
+ data_width = <2 0 0 0>;
+ clocks = <&ahb_clk>;
+ };
+
+ aes: aes@0xe8200000 {
+ compatible = "fh,fh-aes";
+ reg = <0xe8200000 0x1000>;
+ interrupts = <16>;
+ };
+ rtc: rtc@f1500000 {
+ compatible = "fh,fh_rtc";
+ reg = <0xf1500000 0x1000>;
+ interrupts = <33>;
+ clocks = <&rtc_hclk_gate>;
+ lut_cof = <58>;
+ lut_offset = <0xff>;
+ tsensor_cp_default_out = <0x993>;
+ };
+ sadc: sadc@f1200000 {
+ compatible = "fh,fh-sadc";
+ reg = <0xf1200000 0x1000>;
+ interrupts = <20>;
+ ref-vol = <1800>;
+ active-bit = <0xfff>;
+ };
+ efuse: efuse@0xf1600000 {
+ compatible = "fh,fh-efuse";
+ reg = <0xf1600000 0x1000>;
+ key_switch = "enable";
+ indep_power = "enable";
+ };
+ fh_perf: fh_perf@0xf0002018 {
+ compatible = "fh,fh-perf";
+ reg = <0xf0000000 0x4000>;
+ interrupts = < 5 >;
+
+ };
+ spi_bus0: spi@f0500000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0500000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <6>;
+ cs1_gpio = <55>;
+ dma_enable = "disable";
+ swap_support = "enable";
+ rx_hs_no = <4>;
+ tx_hs_no = <5>;
+ bus_no = <0>;
+ multi_wire_size = <2>;
+ clk_name = "spi0_clk";
+ rx_dma_channel = <0>;
+ tx_dma_channel = <1>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <28>;
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fh,m25p80";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ reg = <0x0 0>; //first value means which slave bind to the master. 0 means chip 0. 1 means chip 1
+ partition@0 {
+ reg = <0x0 0x40000>;
+ label = "bootstrap";
+ };
+ partition@40000 {
+ reg = <0x40000 0x10000>;
+ label = "uboot-env";
+ };
+ partition@50000 {
+ reg = <0x50000 0x30000>;
+ label = "uboot";
+ };
+ partition@80000 {
+ reg = <0x80000 0x400000>;
+ label = "kernel";
+ };
+ partition@480000 {
+ reg = <0x480000 0x80000>;
+ label = "rootfs";
+ };
+ partition@500000 {
+ reg = <0x500000 0x300000>;
+ label = "app";
+ };
+
+ };
+ spidev0: spi@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ spi_bus1: spi@f0600000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0600000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <14>;
+ cs1_gpio = <57>;
+ dma_enable = "disable";
+ swap_support = "disable";
+ rx_hs_no = <2>;
+ tx_hs_no = <3>;
+ bus_no = <1>;
+ clk_name = "spi1_clk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <21>;
+ spidev1: spi@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x0 0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev2: spi@2 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ fhdwi2s: i2s@f0900000 {
+ compatible = "fh,fh-dw_i2s";
+ reg = <0xf0900000 0x1000>;
+ interrupts = <25>;
+ clocks = <&i2s_clk>, <&ac_clk>;
+ clock-names = "i2s_clk", "acodec_mclk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ dma_master = <0>;
+ dma_rx_hs_num = <10>;
+ dma_tx_hs_num = <11>;
+ };
+
+ fhacw: acw@f0a00000 {
+ compatible = "fh,fh-acw";
+ reg = <0xf0a00000 0x1000>;
+ interrupts = <19>;
+ clocks = <&ac_clk>;
+ clock-names = "ac_clk";
+ rx_dma_channel = <4>;
+ tx_dma_channel = <5>;
+ dma_master = <0>;
+ dma_rx_hs_num = <0>;
+ dma_tx_hs_num = <1>;
+ };
+
+ pwm: pwm@f0400000{
+ compatible = "fh,fh-pwm";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <36>;
+ npwm = <14>;
+ };
+ serial0: serial@f0700000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0700000 0x1000>;
+ interrupts = <30>;
+ clock-frequency = <16666667>;
+ fifo-size = <32>;
+ };
+ serial1: serial@f0800000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0800000 0x1000>;
+ interrupts = <31>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ serial2: serial@f1300000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf1300000 0x1000>;
+ interrupts = <41>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ gmac0: gmac@e0600000 {
+ compatible = "fh,fh-gmac";
+ reg = <0xe0600000 0x2000>;
+ interrupts = <44>;
+ phyreset-gpio = <29>;
+ };
+ sdc0: sdc0@e2000000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2000000 0x4000>;
+ interrupts = <42>;
+ id = <0>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <0>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <0>;
+ };
+ sdc1: sdc1@e2200000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2200000 0x4000>;
+ interrupts = <43>;
+ id = <1>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <1>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <2>;
+ };
+ wdt: wdt@f0d00000{
+ compatible = "fh,fh-wdt";
+ reg = <0xf0d00000 0x1000>;
+ interrupts = <2>;
+ mode = <1>;
+ };
+ i2cbus0: i2c@f0200000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0200000 0x2000>;
+ interrupts = <11>;
+ };
+ i2cbus1: i2c@f0b00000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0b00000 0x2000>;
+ interrupts = <12>;
+ };
+ i2cbus2: i2c@0xF0100000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xF0100000 0x2000>;
+ interrupts = <46>;
+ };
+ clocks: src_clk@0xf0000000{
+ compatible = "fh,fh-clk";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf0000000 0x80>;
+ ranges;
+
+ osc_clk: mxtal@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_clk";
+ };
+
+ pll_ddr_rclk: pllddrr{
+ #clock-cells = <0>;
+ compatible = "fh pll-ddr-rclk";
+ reg = <0xf0000010 0x4>,<0xf0000018 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_ddr_rclk";
+ };
+ pll_cpu_pclk: pllcpup{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-pclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_pclk";
+ };
+ pll_cpu_rclk: pllcpur{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-rclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_rclk";
+ };
+ pll_sys_pclk: pllsysp{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-pclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_pclk";
+ };
+ pll_sys_rclk: pllsysr{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-rclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_rclk";
+ };
+ sysp_div12_clk: syspdiv12clk{
+ #clock-cells = <0>;
+ compatible = "fh sysp-div12-clk";
+ reg = <0xf0000038 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sysp_div12_clk";
+ };
+ ddr_clk: ddrclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ddr-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clocks = <&pll_ddr_rclk>;
+ clock-output-names = "ddr_clk";
+ };
+ arm_clk: armclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arm-clk";
+ reg = <0x0 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_pclk>;
+ clock-output-names = "arm_clk";
+ };
+ arc_clk: arcclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arc-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ gate = <0x4000000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_rclk>;
+ clock-output-names = "arc_clk";
+ };
+ ahb_clk: ahbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ahb-clk";
+ reg = <0xf0000024 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ div = <0xf0000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_sys_pclk>;
+ clock-output-names = "ahb_clk";
+ };
+ isp_aclk: ispaclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispa-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00>;
+ gate = <0x1>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "isp_aclk";
+ };
+ ispb_aclk: ispbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispb-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "ispb_aclk";
+ };
+ vpu_clk: vpuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80000000>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "vpu_clk";
+ };
+ pix_clk: pixclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-pix-clk";
+ reg = <0xf000002c 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "pix_clk";
+ };
+ jpeg_clk: jpegclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-clk";
+ reg = <0xf000005c 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "jpeg_clk";
+ };
+ bgm_clk: bgmclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "bgm_clk";
+ };
+ jpeg_adapt_clk: jpegadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-adapt-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2>;
+ clocks = <&jpeg_clk>;
+ clock-output-names = "jpeg_adapt_clk";
+ };
+ spi0_clk: spi0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x80>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi0_clk";
+ };
+ sdc0_clk: sdc0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf00>;
+ gate = <0x200>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc0_clk";
+ };
+ spi2_clk: spi2clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi2-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000>;
+ gate = <0x2>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi2_clk";
+ };
+ spi1_clk: spi1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x100>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi1_clk";
+ };
+ sdc1_clk: sdc1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf000000>;
+ gate = <0x400>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc1_clk";
+ };
+ veu_clk: veuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ div = <0x7000000>;
+ gate = <0x10>;
+ mux = <0x4>;
+ clocks = <&pll_sys_pclk>,<&pll_sys_rclk>;
+ clock-output-names = "veu_clk";
+ };
+ veu_adapt_clk: veuadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-adapt-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clocks = <&veu_clk>;
+ clock-output-names = "veu_adapt_clk";
+ };
+ cis_clk_out: cisclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-cis-clk-out";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x800000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "cis_clk_out";
+ };
+ eth_clk: ethclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-eth-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ gate = <0x2000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "eth_clk";
+ };
+ eth_rmii_clk: ethrmiiclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ethrmii-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "eth_rmii_clk";
+ };
+ i2c0_clk: i2c0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f0000>;
+ gate = <0x1000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c0_clk";
+ };
+
+ i2c1_clk: i2c1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x8000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c1_clk";
+ };
+ i2c2_clk: i2c2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x00000008>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c2_clk";
+ };
+
+ uart0_clk: uart0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f>;
+ gate = <0x2000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart0_clk";
+ };
+
+ uart1_clk: uart1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f00>;
+ gate = <0x4000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart1_clk";
+ };
+ uart2_clk: uart2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f>;
+ gate = <0x8000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart2_clk";
+ };
+ pwm_clk: pwmclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pwm-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x10000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pwm_clk";
+ };
+ efuse_clk: efuseclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-efuse-clk";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x200000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "efuse_clk";
+ };
+ pts_clk: ptsclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pts-clk";
+ reg = <0xf000002c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1ff>;
+ gate = <0x80000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pts_clk";
+ };
+ tmr0_clk: tmr0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-tmr0-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x20000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "tmr0_clk";
+ };
+
+ sadc_clk: sadcclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sadc-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f0000>;
+ gate = <0x4000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "sadc_clk";
+ };
+ gpio0_dbclk: gpio0dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff>;
+ gate = <0x8000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio0_dbclk";
+ };
+ gpio1_dbclk: gpio1dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff0000>;
+ gate = <0x80000000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio1_dbclk";
+ };
+ wdt_clk: wdtclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-wdt-clk";
+ reg = <0xf0000038 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xff00>;
+ gate = <0x8000000>;
+ clocks = <&ahb_clk>;
+ clock-output-names = "wdt_clk";
+ };
+ ac_clk: acclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ac-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f>;
+ gate = <0x800>;
+ clocks = <&osc_clk>;
+ clock-output-names = "ac_clk";
+ };
+ i2s_clk: i2sclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-i2s-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x1000000>;
+ clocks = <&ac_clk>;
+ clock-output-names = "i2s_clk";
+ };
+ mipi_dphy_clk: mipidphyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-dphy-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x100000>;
+ clock-output-names = "mipi_dphy_clk";
+ };
+ mipi_wrap_gate: mipiwrapclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-wrap-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "mipi_wrap_gate";
+ };
+ rtc_hclk_gate: rtchclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-rtc-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "rtc_hclk_gate";
+ };
+ emac_hclk_gate: emachclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-emac-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "emac_hclk_gate";
+ };
+ usb_clk: usbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-usb-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "usb_clk";
+ };
+ aes_hclk_gate: aeshclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-aes-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80>;
+ clock-output-names = "aes_hclk_gate";
+ };
+ ephy_clk_gate: ephyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ephy-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1>;
+ clock-output-names = "ephy_clk_gate";
+ };
+ sdc0_clk8x_gate: sdc08xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc08x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clock-output-names = "sdc0_clk8x_gate";
+ };
+ sdc1_clk8x_gate: sdc18xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc18x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x8>;
+ clock-output-names = "sdc1_clk8x_gate";
+ };
+ mipic_pclk_gate: mipicpclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipic-pclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10>;
+ clock-output-names = "mipic_pclk_gate";
+ };
+ gpio0_pclk_gate: gpio0pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x4000>;
+ clock-output-names = "gpio0_pclk_gate";
+ };
+ gpio1_pclk_gate: gpio1pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "gpio1_pclk_gate";
+ };
+ isp_hclk_gate: isphclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-isp-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "isp_hclk_gate";
+ };
+ veu_hclk_gate: veuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "veu_hclk_gate";
+ };
+ bgm_hclk_gate: bgmhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clock-output-names = "bgm_hclk_gate";
+ };
+ adapt_hclk_gate: adapthclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-adapt-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x8000000>;
+ clock-output-names = "adapt_hclk_gate";
+ };
+ jpg_hclk_gate: jpghclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "jpg_hclk_gate";
+ };
+ jpg_adapt_gate: jpgadaptclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-adapt-clk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "jpg_adapt_gate";
+ };
+ vpu_hclk_gate: vpuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "vpu_hclk_gate";
+ };
+ sdc0_clk_sample: sdc0clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf0000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_sample";
+ };
+ sdc0_clk_drv: sdc0clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_drv";
+ };
+
+ sdc1_clk_sample: sdc1clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_sample";
+ };
+
+ sdc1_clk_drv: sdc1clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf000>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_drv";
+ };
+ };
+ };
+
+ usb_otg@e0700000 {
+ compatible = "fh_usb";
+ reg = <0xe0700000 100000>;
+ interrupts = <39>;
+ clocks = <&usb_clk>;
+ dr_mode = "host";
+ vbus_pwren = <47>;
+ clock-names = "otg";
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
+ };
+
+ usb2_phy: usbphy {
+ compatible = "fh,fh-usb2-phy";
+ #phy-cells = <0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/fh8858v200_pinctrl.dtsi b/arch/arm/boot/dts/fh8858v200_pinctrl.dtsi
new file mode 100644
index 00000000..f4cd0f03
--- /dev/null
+++ b/arch/arm/boot/dts/fh8858v200_pinctrl.dtsi
@@ -0,0 +1,2379 @@
+/*
+ * Copyright (C) 2020 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ #define PUPD_NONE (0)
+ #define PUPD_UP (1)
+ #define PUPD_DOWN (2)
+*/
+
+/ {
+ pinctrl: pinctrl@f0000080 {
+ compatible = "fh,fh-pinctrl";
+ reg = <0xf0000080 0x104>;
+ pad-num = <65>;
+ max-mux = <9>;
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_AC_MCLK
+ &pinctrl_ETH
+ &pinctrl_I2C0
+ &pinctrl_PWM2
+ &pinctrl_PWM3
+ &pinctrl_PWM4
+ &pinctrl_PWM5
+ &pinctrl_PWM6
+ &pinctrl_PWM7
+ &pinctrl_PWM8
+ &pinctrl_PWM9
+ &pinctrl_SADC_XAIN0
+ &pinctrl_SADC_XAIN1
+ &pinctrl_SADC_XAIN2
+ &pinctrl_SADC_XAIN3
+ &pinctrl_SD0_NO_WP
+ &pinctrl_SD1_NO_WP
+ &pinctrl_SENSOR_CLK
+ &pinctrl_SSI0_4BIT
+ &pinctrl_SSI1
+ &pinctrl_UART0
+ &pinctrl_UART1
+ &pinctrl_GPIO13
+ &pinctrl_GPIO28
+ &pinctrl_GPIO29
+ &pinctrl_GPIO30
+ &pinctrl_GPIO31
+ &pinctrl_GPIO32
+ &pinctrl_GPIO43
+ &pinctrl_GPIO44
+ &pinctrl_GPIO47
+ &pinctrl_GPIO48
+ &pinctrl_GPIO49
+ &pinctrl_GPIO50
+ &pinctrl_GPIO51
+ &pinctrl_GPIO52
+ &pinctrl_GPIO53
+ &pinctrl_GPIO54
+ &pinctrl_GPIO55
+ &pinctrl_GPIO56
+
+ &pinctrl_GPIO45
+ &pinctrl_GPIO46
+ >;
+ pinctrl_groups {
+ pinctrl_ACI2S: ACI2S {
+ fh,pins = <
+ &mux_AC_I2S_CLK 0
+ &mux_AC_I2S_DI 0
+ &mux_AC_I2S_DO 0
+ &mux_AC_I2S_WS 0
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_AC_MCLK: AC_MCLK {
+ fh,pins = <
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_ARCJTAG: ARCJTAG {
+ fh,pins = <
+ &mux_ARC_JTAG_TCK 0
+ &mux_ARC_JTAG_TDI 0
+ &mux_ARC_JTAG_TDO 0
+ &mux_ARC_JTAG_TMS 0
+ &mux_ARC_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_ARMJTAG: ARMJTAG {
+ fh,pins = <
+ &mux_ARM_JTAG_TCK 0
+ &mux_ARM_JTAG_TDI 0
+ &mux_ARM_JTAG_TDO 0
+ &mux_ARM_JTAG_TMS 0
+ &mux_ARM_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_DWI2S: DWI2S {
+ fh,pins = <
+ &mux_DW_I2S_CLK 0
+ &mux_DW_I2S_DI 0
+ &mux_DW_I2S_DO 0
+ &mux_DW_I2S_WS 0
+ >;
+ };
+ pinctrl_ETH: ETH {
+ fh,pins = <
+ &mux_ETH_LINK_ACT 1
+ &mux_ETH_LINK_STA 1
+ >;
+ };
+ pinctrl_I2C0: I2C0 {
+ fh,pins = <
+ &mux_I2C0_SCL 0
+ &mux_I2C0_SDA 0
+ >;
+ };
+ pinctrl_I2C1: I2C1 {
+ fh,pins = <
+ &mux_I2C1_SCL 2
+ &mux_I2C1_SDA 2
+ >;
+ };
+ pinctrl_I2C2: I2C2 {
+ fh,pins = <
+ &mux_I2C2_SCL 1
+ &mux_I2C2_SDA 1
+ >;
+ };
+ pinctrl_PAEJTAG: PAEJTAG {
+ fh,pins = <
+ &mux_PAE_JTAG_TCK 0
+ &mux_PAE_JTAG_TDI 0
+ &mux_PAE_JTAG_TDO 0
+ &mux_PAE_JTAG_TMS 0
+ &mux_PAE_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_PWM0: PWM0 {
+ fh,pins = <
+ &mux_PWM0 0
+ >;
+ };
+ pinctrl_PWM1: PWM1 {
+ fh,pins = <
+ &mux_PWM1 0
+ >;
+ };
+ pinctrl_PWM10: PWM10 {
+ fh,pins = <
+ &mux_PWM10 0
+ >;
+ };
+ pinctrl_PWM11: PWM11 {
+ fh,pins = <
+ &mux_PWM11 0
+ >;
+ };
+ pinctrl_PWM2: PWM2 {
+ fh,pins = <
+ &mux_PWM2 0
+ >;
+ };
+ pinctrl_PWM3: PWM3 {
+ fh,pins = <
+ &mux_PWM3 0
+ >;
+ };
+ pinctrl_PWM4: PWM4 {
+ fh,pins = <
+ &mux_PWM4 0
+ >;
+ };
+ pinctrl_PWM5: PWM5 {
+ fh,pins = <
+ &mux_PWM5 0
+ >;
+ };
+ pinctrl_PWM6: PWM6 {
+ fh,pins = <
+ &mux_PWM6 1
+ >;
+ };
+ pinctrl_PWM7: PWM7 {
+ fh,pins = <
+ &mux_PWM7 1
+ >;
+ };
+ pinctrl_PWM8: PWM8 {
+ fh,pins = <
+ &mux_PWM8 1
+ >;
+ };
+ pinctrl_PWM9: PWM9 {
+ fh,pins = <
+ &mux_PWM9 1
+ >;
+ };
+ pinctrl_RMII: RMII {
+ fh,pins = <
+ &mux_MAC_MDC 0
+ &mux_MAC_MDIO 0
+ &mux_MAC_REF_CLK 0
+ &mux_MAC_RMII_CLK 0
+ &mux_MAC_RXDV 0
+ &mux_MAC_RXD_0 0
+ &mux_MAC_RXD_1 0
+ &mux_MAC_TXD_0 0
+ &mux_MAC_TXD_1 0
+ &mux_MAC_TXEN 0
+ >;
+ };
+ pinctrl_RTC: RTC {
+ fh,pins = <
+ &mux_RTC_CLK 0
+ >;
+ };
+ pinctrl_SADC_XAIN0: SADC_XAIN0 {
+ fh,pins = <
+ &mux_SADC_XAIN0 0
+ >;
+ };
+ pinctrl_SADC_XAIN1: SADC_XAIN1 {
+ fh,pins = <
+ &mux_SADC_XAIN1 0
+ >;
+ };
+ pinctrl_SADC_XAIN2: SADC_XAIN2 {
+ fh,pins = <
+ &mux_SADC_XAIN2 0
+ >;
+ };
+ pinctrl_SADC_XAIN3: SADC_XAIN3 {
+ fh,pins = <
+ &mux_SADC_XAIN3 0
+ >;
+ };
+ pinctrl_SD0: SD0 {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_1BIT_NO_WP: SD0_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ >;
+ };
+ pinctrl_SD0_NO_WP: SD0_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_WIFI: SD0_WIFI {
+ fh,pins = <
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD1: SD1 {
+ fh,pins = <
+ &mux_SD1_CD 2
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ &mux_SD1_DATA_1 2
+ &mux_SD1_DATA_2 2
+ &mux_SD1_DATA_3 2
+ >;
+ };
+ pinctrl_SD1_1BIT_NO_WP: SD1_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 2
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ >;
+ };
+ pinctrl_SD1_NO_WP: SD1_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 2
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ &mux_SD1_DATA_1 2
+ &mux_SD1_DATA_2 2
+ &mux_SD1_DATA_3 2
+ >;
+ };
+ pinctrl_SD1_WIFI: SD1_WIFI {
+ fh,pins = <
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ &mux_SD1_DATA_1 2
+ &mux_SD1_DATA_2 2
+ &mux_SD1_DATA_3 2
+ >;
+ };
+ pinctrl_SENSOR_CLK: SENSOR_CLK {
+ fh,pins = <
+ &mux_SENSOR_CLK 0
+ >;
+ };
+ pinctrl_SSI0: SSI0 {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI0_4BIT: SSI0_4BIT {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_D2 0
+ &mux_SSI0_D3 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI1: SSI1 {
+ fh,pins = <
+ &mux_GPIO14 0
+ &mux_SSI1_CLK 2
+ &mux_SSI1_RXD 2
+ &mux_SSI1_TXD 2
+ >;
+ };
+ pinctrl_SSI2: SSI2 {
+ fh,pins = <
+ &mux_SSI2_CLK 1
+ &mux_SSI2_CSN_0 1
+ &mux_SSI2_RXD 1
+ &mux_SSI2_TXD 1
+ >;
+ };
+ pinctrl_UART0: UART0 {
+ fh,pins = <
+ &mux_UART0_RX 0
+ &mux_UART0_TX 0
+ >;
+ };
+ pinctrl_UART1: UART1 {
+ fh,pins = <
+ &mux_UART1_RX 0
+ &mux_UART1_TX 0
+ >;
+ };
+ pinctrl_UART2: UART2 {
+ fh,pins = <
+ &mux_UART2_RX 0
+ &mux_UART2_TX 0
+ >;
+ };
+ pinctrl_USB: USB {
+ fh,pins = <
+ &mux_USB_PWREN 0
+ >;
+ };
+ pinctrl_GPIO0: GPIO0 {
+ fh,pins = <
+ &mux_GPIO0 0
+ >;
+ };
+ pinctrl_GPIO1: GPIO1 {
+ fh,pins = <
+ &mux_GPIO1 0
+ >;
+ };
+ pinctrl_GPIO2: GPIO2 {
+ fh,pins = <
+ &mux_GPIO2 0
+ >;
+ };
+ pinctrl_GPIO3: GPIO3 {
+ fh,pins = <
+ &mux_GPIO3 0
+ >;
+ };
+ pinctrl_GPIO4: GPIO4 {
+ fh,pins = <
+ &mux_GPIO4 0
+ >;
+ };
+ pinctrl_GPIO5: GPIO5 {
+ fh,pins = <
+ &mux_GPIO5 0
+ >;
+ };
+ pinctrl_GPIO6: GPIO6 {
+ fh,pins = <
+ &mux_GPIO6 0
+ >;
+ };
+ pinctrl_GPIO7: GPIO7 {
+ fh,pins = <
+ &mux_GPIO7 0
+ >;
+ };
+ pinctrl_GPIO8: GPIO8 {
+ fh,pins = <
+ &mux_GPIO8 0
+ >;
+ };
+ pinctrl_GPIO9: GPIO9 {
+ fh,pins = <
+ &mux_GPIO9 0
+ >;
+ };
+ pinctrl_GPIO10: GPIO10 {
+ fh,pins = <
+ &mux_GPIO10 0
+ >;
+ };
+ pinctrl_GPIO11: GPIO11 {
+ fh,pins = <
+ &mux_GPIO11 0
+ >;
+ };
+ pinctrl_GPIO12: GPIO12 {
+ fh,pins = <
+ &mux_GPIO12 0
+ >;
+ };
+ pinctrl_GPIO13: GPIO13 {
+ fh,pins = <
+ &mux_GPIO13 0
+ >;
+ };
+ pinctrl_GPIO14: GPIO14 {
+ fh,pins = <
+ &mux_GPIO14 0
+ >;
+ };
+ pinctrl_GPIO15: GPIO15 {
+ fh,pins = <
+ &mux_GPIO15 0
+ >;
+ };
+ pinctrl_GPIO16: GPIO16 {
+ fh,pins = <
+ &mux_GPIO16 0
+ >;
+ };
+ pinctrl_GPIO17: GPIO17 {
+ fh,pins = <
+ &mux_GPIO17 0
+ >;
+ };
+ pinctrl_GPIO18: GPIO18 {
+ fh,pins = <
+ &mux_GPIO18 0
+ >;
+ };
+ pinctrl_GPIO19: GPIO19 {
+ fh,pins = <
+ &mux_GPIO19 0
+ >;
+ };
+ pinctrl_GPIO20: GPIO20 {
+ fh,pins = <
+ &mux_GPIO20 0
+ >;
+ };
+ pinctrl_GPIO21: GPIO21 {
+ fh,pins = <
+ &mux_GPIO21 0
+ >;
+ };
+ pinctrl_GPIO22: GPIO22 {
+ fh,pins = <
+ &mux_GPIO22 0
+ >;
+ };
+ pinctrl_GPIO23: GPIO23 {
+ fh,pins = <
+ &mux_GPIO23 0
+ >;
+ };
+ pinctrl_GPIO24: GPIO24 {
+ fh,pins = <
+ &mux_GPIO24 0
+ >;
+ };
+ pinctrl_GPIO25: GPIO25 {
+ fh,pins = <
+ &mux_GPIO25 0
+ >;
+ };
+ pinctrl_GPIO26: GPIO26 {
+ fh,pins = <
+ &mux_GPIO26 0
+ >;
+ };
+ pinctrl_GPIO27: GPIO27 {
+ fh,pins = <
+ &mux_GPIO27 0
+ >;
+ };
+ pinctrl_GPIO28: GPIO28 {
+ fh,pins = <
+ &mux_GPIO28 0
+ >;
+ };
+ pinctrl_GPIO29: GPIO29 {
+ fh,pins = <
+ &mux_GPIO29 0
+ >;
+ };
+ pinctrl_GPIO30: GPIO30 {
+ fh,pins = <
+ &mux_GPIO30 0
+ >;
+ };
+ pinctrl_GPIO31: GPIO31 {
+ fh,pins = <
+ &mux_GPIO31 0
+ >;
+ };
+ pinctrl_GPIO32: GPIO32 {
+ fh,pins = <
+ &mux_GPIO32 0
+ >;
+ };
+ pinctrl_GPIO33: GPIO33 {
+ fh,pins = <
+ &mux_GPIO33 0
+ >;
+ };
+ pinctrl_GPIO34: GPIO34 {
+ fh,pins = <
+ &mux_GPIO34 0
+ >;
+ };
+ pinctrl_GPIO35: GPIO35 {
+ fh,pins = <
+ &mux_GPIO35 0
+ >;
+ };
+ pinctrl_GPIO36: GPIO36 {
+ fh,pins = <
+ &mux_GPIO36 0
+ >;
+ };
+ pinctrl_GPIO37: GPIO37 {
+ fh,pins = <
+ &mux_GPIO37 0
+ >;
+ };
+ pinctrl_GPIO38: GPIO38 {
+ fh,pins = <
+ &mux_GPIO38 0
+ >;
+ };
+ pinctrl_GPIO39: GPIO39 {
+ fh,pins = <
+ &mux_GPIO39 0
+ >;
+ };
+ pinctrl_GPIO40: GPIO40 {
+ fh,pins = <
+ &mux_GPIO40 0
+ >;
+ };
+ pinctrl_GPIO41: GPIO41 {
+ fh,pins = <
+ &mux_GPIO41 0
+ >;
+ };
+ pinctrl_GPIO42: GPIO42 {
+ fh,pins = <
+ &mux_GPIO42 0
+ >;
+ };
+ pinctrl_GPIO43: GPIO43 {
+ fh,pins = <
+ &mux_GPIO43 0
+ >;
+ };
+ pinctrl_GPIO44: GPIO44 {
+ fh,pins = <
+ &mux_GPIO44 0
+ >;
+ };
+ pinctrl_GPIO45: GPIO45 {
+ fh,pins = <
+ &mux_GPIO45 0
+ >;
+ };
+ pinctrl_GPIO46: GPIO46 {
+ fh,pins = <
+ &mux_GPIO46 0
+ >;
+ };
+ pinctrl_GPIO47: GPIO47 {
+ fh,pins = <
+ &mux_GPIO47 0
+ >;
+ };
+ pinctrl_GPIO48: GPIO48 {
+ fh,pins = <
+ &mux_GPIO48 0
+ >;
+ };
+ pinctrl_GPIO49: GPIO49 {
+ fh,pins = <
+ &mux_GPIO49 0
+ >;
+ };
+ pinctrl_GPIO50: GPIO50 {
+ fh,pins = <
+ &mux_GPIO50 0
+ >;
+ };
+ pinctrl_GPIO51: GPIO51 {
+ fh,pins = <
+ &mux_GPIO51 0
+ >;
+ };
+ pinctrl_GPIO52: GPIO52 {
+ fh,pins = <
+ &mux_GPIO52 0
+ >;
+ };
+ pinctrl_GPIO53: GPIO53 {
+ fh,pins = <
+ &mux_GPIO53 0
+ >;
+ };
+ pinctrl_GPIO54: GPIO54 {
+ fh,pins = <
+ &mux_GPIO54 0
+ >;
+ };
+ pinctrl_GPIO55: GPIO55 {
+ fh,pins = <
+ &mux_GPIO55 0
+ >;
+ };
+ pinctrl_GPIO56: GPIO56 {
+ fh,pins = <
+ &mux_GPIO56 0
+ >;
+ };
+ pinctrl_GPIO57: GPIO57 {
+ fh,pins = <
+ &mux_GPIO57 0
+ >;
+ };
+ pinctrl_GPIO58: GPIO58 {
+ fh,pins = <
+ &mux_GPIO58 0
+ >;
+ };
+ pinctrl_GPIO59: GPIO59 {
+ fh,pins = <
+ &mux_GPIO59 0
+ >;
+ };
+ pinctrl_GPIO60: GPIO60 {
+ fh,pins = <
+ &mux_GPIO60 0
+ >;
+ };
+ pinctrl_GPIO61: GPIO61 {
+ fh,pins = <
+ &mux_GPIO61 0
+ >;
+ };
+ pinctrl_GPIO62: GPIO62 {
+ fh,pins = <
+ &mux_GPIO62 0
+ >;
+ };
+ pinctrl_GPIO63: GPIO63 {
+ fh,pins = <
+ &mux_GPIO63 0
+ >;
+ };
+ pinctrl_SD1_EMMC: SD1_EMMC {
+ fh,pins = <
+ &mux_SD1_CD 3
+ &mux_SD1_CLK 3
+ &mux_SD1_CMD_RSP 3
+ &mux_SD1_DATA_0 3
+ &mux_SD1_DATA_1 3
+ &mux_SD1_DATA_2 3
+ &mux_SD1_DATA_3 3
+ >;
+ };
+ };
+ pinmux: pinmux {
+ compatible = "fh,fh-pinmux";
+ #list-cells = <1>;
+ mux_AC_I2S_CLK: AC_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_AC_I2S_DI: AC_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_AC_I2S_DO: AC_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_AC_I2S_WS: AC_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_AC_MCLK: AC_MCLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+
+ mux_ARC_JTAG_TCK: ARC_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_ARC_JTAG_TDI: ARC_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_ARC_JTAG_TDO: ARC_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_ARC_JTAG_TMS: ARC_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_ARC_JTAG_TRSTN: ARC_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_ARM_JTAG_TCK: ARM_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_ARM_JTAG_TDI: ARM_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_ARM_JTAG_TDO: ARM_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_ARM_JTAG_TMS: ARM_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_ARM_JTAG_TRSTN: ARM_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+
+ mux_DW_I2S_CLK: DW_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_DW_I2S_DI: DW_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_DW_I2S_DO: DW_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_DW_I2S_WS: DW_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+
+ mux_ETH_LINK_ACT: ETH_LINK_ACT {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad1
+ &pad63
+ >;
+ };
+ mux_ETH_LINK_SPD: ETH_LINK_SPD {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+ mux_ETH_LINK_STA: ETH_LINK_STA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+
+ mux_I2C0_SCL: I2C0_SCL {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_I2C0_SDA: I2C0_SDA {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+
+ mux_I2C1_SCL: I2C1_SCL {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad11
+ &pad30
+ &pad46
+ >;
+ };
+ mux_I2C1_SDA: I2C1_SDA {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad12
+ &pad31
+ &pad47
+ >;
+ };
+
+ mux_I2C2_SCL: I2C2_SCL {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad16
+ &pad57
+ >;
+ };
+ mux_I2C2_SDA: I2C2_SDA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad17
+ &pad58
+ >;
+ };
+
+ mux_MAC_MDC: MAC_MDC {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <0>;
+ fh,pads = <
+ &pad28
+ &pad63
+ >;
+ };
+ mux_MAC_MDIO: MAC_MDIO {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <0>;
+ fh,pads = <
+ &pad29
+ &pad64
+ >;
+ };
+ mux_MAC_REF_CLK: MAC_REF_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad21
+ >;
+ };
+ mux_MAC_RMII_CLK: MAC_RMII_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_MAC_RXDV: MAC_RXDV {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_MAC_RXD_0: MAC_RXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_MAC_RXD_1: MAC_RXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_MAC_TXD_0: MAC_TXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_MAC_TXD_1: MAC_TXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_MAC_TXEN: MAC_TXEN {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+
+ mux_PAE_JTAG_TCK: PAE_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_PAE_JTAG_TDI: PAE_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_PAE_JTAG_TDO: PAE_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_PAE_JTAG_TMS: PAE_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_PAE_JTAG_TRSTN: PAE_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_PWM0: PWM0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_PWM1: PWM1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_PWM10: PWM10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_PWM11: PWM11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_PWM2: PWM2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ &pad18
+ &pad20
+ >;
+ };
+ mux_PWM3: PWM3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ &pad19
+ &pad22
+ >;
+ };
+ mux_PWM4: PWM4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad23
+ >;
+ };
+ mux_PWM5: PWM5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad24
+ >;
+ };
+ mux_PWM6: PWM6 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad25
+ &pad37
+ >;
+ };
+ mux_PWM7: PWM7 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad26
+ &pad38
+ >;
+ };
+ mux_PWM8: PWM8 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad27
+ &pad39
+ >;
+ };
+ mux_PWM9: PWM9 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad28
+ &pad40
+ >;
+ };
+
+ mux_RTC_CLK: RTC_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+
+ mux_SADC_XAIN0: SADC_XAIN0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_SADC_XAIN1: SADC_XAIN1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_SADC_XAIN2: SADC_XAIN2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_SADC_XAIN3: SADC_XAIN3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+
+ mux_SD0_CD: SD0_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_SD0_CLK: SD0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_SD0_CMD_RSP: SD0_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_SD0_DATA_0: SD0_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_SD0_DATA_1: SD0_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_SD0_DATA_2: SD0_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_SD0_DATA_3: SD0_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+
+ mux_SD1_CD: SD1_CD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad10
+ &pad22
+ &pad31
+ &pad41
+ &pad63
+ >;
+ };
+ mux_SD1_CLK: SD1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad9
+ &pad20
+ &pad30
+ &pad42
+ >;
+ };
+ mux_SD1_CMD_RSP: SD1_CMD_RSP {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad23
+ &pad32
+ &pad43
+ >;
+ };
+ mux_SD1_DATA_0: SD1_DATA_0 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad12
+ &pad24
+ &pad33
+ &pad44
+ >;
+ };
+ mux_SD1_DATA_1: SD1_DATA_1 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad25
+ &pad34
+ &pad45
+ >;
+ };
+ mux_SD1_DATA_2: SD1_DATA_2 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad26
+ &pad35
+ &pad46
+ >;
+ };
+ mux_SD1_DATA_3: SD1_DATA_3 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad15
+ &pad27
+ &pad36
+ &pad47
+ >;
+ };
+
+ mux_SENSOR_CLK: SENSOR_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+
+ mux_SSI0_CLK: SSI0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_SSI0_D2: SSI0_D2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_SSI0_D3: SSI0_D3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_SSI0_RXD: SSI0_RXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_SSI0_TXD: SSI0_TXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+
+ mux_SSI1_CLK: SSI1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad37
+ &pad48
+ &pad53
+ >;
+ };
+ mux_SSI1_RXD: SSI1_RXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad40
+ &pad51
+ &pad55
+ >;
+ };
+ mux_SSI1_TXD: SSI1_TXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad39
+ &pad50
+ &pad54
+ >;
+ };
+
+ mux_SSI2_CLK: SSI2_CLK {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad37
+ &pad48
+ >;
+ };
+ mux_SSI2_CSN_0: SSI2_CSN_0 {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad38
+ &pad49
+ >;
+ };
+ mux_SSI2_RXD: SSI2_RXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad40
+ &pad51
+ >;
+ };
+ mux_SSI2_TXD: SSI2_TXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad39
+ &pad50
+ >;
+ };
+
+ mux_UART0_RX: UART0_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_UART0_TX: UART0_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+
+ mux_UART1_RX: UART1_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ &pad33
+ &pad47
+ >;
+ };
+ mux_UART1_TX: UART1_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ &pad32
+ &pad46
+ >;
+ };
+
+ mux_UART2_RX: UART2_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad17
+ &pad35
+ &pad58
+ >;
+ };
+ mux_UART2_TX: UART2_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad16
+ &pad34
+ &pad57
+ >;
+ };
+
+ mux_USB_PWREN: USB_PWREN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ &pad41
+ >;
+ };
+
+ mux_GPIO0: GPIO0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_GPIO1: GPIO1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_GPIO2: GPIO2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_GPIO3: GPIO3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_GPIO4: GPIO4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_GPIO5: GPIO5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_GPIO6: GPIO6 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad43
+ >;
+ };
+ mux_GPIO7: GPIO7 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+ mux_GPIO8: GPIO8 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_GPIO9: GPIO9 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_GPIO10: GPIO10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_GPIO11: GPIO11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad48
+ >;
+ };
+ mux_GPIO12: GPIO12 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+ mux_GPIO13: GPIO13 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad8
+ >;
+ };
+ mux_GPIO14: GPIO14 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad49
+ >;
+ };
+ mux_GPIO15: GPIO15 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad50
+ >;
+ };
+ mux_GPIO16: GPIO16 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad51
+ >;
+ };
+ mux_GPIO17: GPIO17 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_GPIO18: GPIO18 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_GPIO19: GPIO19 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_GPIO20: GPIO20 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_GPIO21: GPIO21 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_GPIO22: GPIO22 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_GPIO23: GPIO23 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+ mux_GPIO24: GPIO24 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_GPIO25: GPIO25 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+ mux_GPIO26: GPIO26 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_GPIO27: GPIO27 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_GPIO28: GPIO28 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_GPIO29: GPIO29 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_GPIO30: GPIO30 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad0
+ >;
+ };
+ mux_GPIO31: GPIO31 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad1
+ >;
+ };
+ mux_GPIO32: GPIO32 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad2
+ >;
+ };
+ mux_GPIO33: GPIO33 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+ mux_GPIO34: GPIO34 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_GPIO35: GPIO35 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_GPIO36: GPIO36 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+ mux_GPIO37: GPIO37 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ >;
+ };
+ mux_GPIO38: GPIO38 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ >;
+ };
+ mux_GPIO39: GPIO39 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ >;
+ };
+ mux_GPIO40: GPIO40 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ >;
+ };
+ mux_GPIO41: GPIO41 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ >;
+ };
+ mux_GPIO42: GPIO42 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ >;
+ };
+ mux_GPIO43: GPIO43 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_GPIO44: GPIO44 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_GPIO45: GPIO45 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad18
+ >;
+ };
+ mux_GPIO46: GPIO46 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad19
+ >;
+ };
+ mux_GPIO47: GPIO47 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ >;
+ };
+ mux_GPIO48: GPIO48 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_GPIO49: GPIO49 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_GPIO50: GPIO50 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_GPIO51: GPIO51 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+ mux_GPIO52: GPIO52 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_GPIO53: GPIO53 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_GPIO54: GPIO54 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_GPIO55: GPIO55 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad28
+ >;
+ };
+ mux_GPIO56: GPIO56 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad29
+ >;
+ };
+ mux_GPIO57: GPIO57 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad30
+ >;
+ };
+ mux_GPIO58: GPIO58 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad31
+ >;
+ };
+ mux_GPIO59: GPIO59 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad32
+ >;
+ };
+ mux_GPIO60: GPIO60 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad33
+ >;
+ };
+ mux_GPIO61: GPIO61 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad34
+ >;
+ };
+ mux_GPIO62: GPIO62 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad35
+ >;
+ };
+ mux_GPIO63: GPIO63 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad36
+ >;
+ };
+ };
+ pinpad: pinpad {
+ compatible = "fh,fh-pinpad";
+ pad0: PAD_BOOT_MODE_CFG {
+ index = <0>;
+ funcs = "GPIO30";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad1: PAD_BOOT_SEL1_CFG {
+ index = <1>;
+ funcs = "GPIO31", "ETH_LINK_ACT";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad2: PAD_BOOT_SEL0_CFG {
+ index = <2>;
+ funcs = "GPIO32", "ETH_LINK_STA", "ETH_LINK_SPD";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad3: PAD_UART0_TX_CFG {
+ index = <3>;
+ funcs = "UART0_TX", "GPIO33";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad4: PAD_UART0_RX_CFG {
+ index = <4>;
+ funcs = "UART0_RX", "GPIO34";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad5: PAD_I2C0_SCL_CFG {
+ index = <5>;
+ funcs = "I2C0_SCL", "GPIO35";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad6: PAD_I2C0_SDA_CFG {
+ index = <6>;
+ funcs = "I2C0_SDA", "GPIO36";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad7: PAD_SENSOR_CLK_CFG {
+ index = <7>;
+ funcs = "SENSOR_CLK", "GPIO12";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad8: PAD_SENSOR_RSTN_CFG {
+ index = <8>;
+ funcs = "GPIO13";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad9: PAD_UART1_TX_CFG {
+ index = <9>;
+ funcs = "UART1_TX", "GPIO39", "", "SD1_CLK", "", "",
+ "TEST_O_INT_RMII_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad10: PAD_UART1_RX_CFG {
+ index = <10>;
+ funcs = "UART1_RX", "GPIO40", "", "SD1_CD", "", "",
+ "TEST_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad11: PAD_I2C1_SCL_CFG {
+ index = <11>;
+ funcs = "I2C1_SCL", "GPIO37", "PWM2", "SD1_CMD_RSP", "",
+ "SSI1_CLK", "TEST_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad12: PAD_I2C1_SDA_CFG {
+ index = <12>;
+ funcs = "I2C1_SDA", "GPIO38", "PWM3", "SD1_DATA_0", "",
+ "SSI1_CSN_0", "TEST_INT_RMII_TXEN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad13: PAD_UART2_TX_CFG {
+ index = <13>;
+ funcs = "UART2_TX", "GPIO41", "PWM4", "SD1_DATA_1", "",
+ "SSI1_TXD", "TEST_O_INT_RMII_RXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad14: PAD_UART2_RX_CFG {
+ index = <14>;
+ funcs = "UART2_RX", "GPIO42", "PWM5", "SD1_DATA_2", "",
+ "SSI1_RXD", "TEST_O_INT_RMII_RXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad15: PAD_USB_PWREN_CFG {
+ index = <15>;
+ funcs = "USB_PWREN", "GPIO47", "", "SD1_DATA_3", "", "",
+ "TEST_O_INT_RMII_CRSDV";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad16: PAD_PWM0_CFG {
+ index = <16>;
+ funcs = "PWM0", "GPIO43", "I2C2_SCL", "UART2_TX", "", "",
+ "TEST_O_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad17: PAD_PWM1_CFG {
+ index = <17>;
+ funcs = "PWM1", "GPIO44", "I2C2_SDA", "UART2_RX", "", "",
+ "TEST_O_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad18: PAD_PWM2_CFG {
+ index = <18>;
+ funcs = "PWM2", "GPIO45";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad19: PAD_PWM3_CFG {
+ index = <19>;
+ funcs = "PWM3", "GPIO46";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad20: PAD_MAC_RMII_CLK_CFG {
+ index = <20>;
+ funcs = "MAC_RMII_CLK", "GPIO48", "SD1_CLK", "PWM2";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad21: PAD_MAC_REF_CLK_CFG {
+ index = <21>;
+ funcs = "MAC_REF_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad22: PAD_MAC_TXD0_CFG {
+ index = <22>;
+ funcs = "MAC_TXD_0", "GPIO49", "SD1_CD", "PWM3";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad23: PAD_MAC_TXD1_CFG {
+ index = <23>;
+ funcs = "MAC_TXD_1", "GPIO50", "SD1_CMD_RSP", "PWM4";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad24: PAD_MAC_TXEN_CFG {
+ index = <24>;
+ funcs = "MAC_TXEN", "GPIO51", "SD1_DATA_0", "PWM5";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad25: PAD_MAC_RXD0_CFG {
+ index = <25>;
+ funcs = "MAC_RXD_0", "GPIO52", "SD1_DATA_1", "PWM6";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad26: PAD_MAC_RXD1_CFG {
+ index = <26>;
+ funcs = "MAC_RXD_1", "GPIO53", "SD1_DATA_2", "PWM7";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad27: PAD_MAC_RXDV_CFG {
+ index = <27>;
+ funcs = "MAC_RXDV", "GPIO54", "SD1_DATA_3", "PWM8";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad28: PAD_MAC_MDC_CFG {
+ index = <28>;
+ funcs = "MAC_MDC", "GPIO55", "", "PWM9";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad29: PAD_MAC_MDIO_CFG {
+ index = <29>;
+ funcs = "MAC_MDIO", "GPIO56";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad30: PAD_SD1_CLK_CFG {
+ index = <30>;
+ funcs = "SD1_CLK", "GPIO57", "I2C1_SCL";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad31: PAD_SD1_CD_CFG {
+ index = <31>;
+ funcs = "SD1_CD", "GPIO58", "I2C1_SDA";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad32: PAD_SD1_CMD_RSP_CFG {
+ index = <32>;
+ funcs = "SD1_CMD_RSP", "GPIO59", "UART1_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad33: PAD_SD1_DATA_0_CFG {
+ index = <33>;
+ funcs = "SD1_DATA_0", "GPIO60", "UART1_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad34: PAD_SD1_DATA_1_CFG {
+ index = <34>;
+ funcs = "SD1_DATA_1", "GPIO61", "UART2_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad35: PAD_SD1_DATA_2_CFG {
+ index = <35>;
+ funcs = "SD1_DATA_2", "GPIO62", "UART2_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad36: PAD_SD1_DATA_3_CFG {
+ index = <36>;
+ funcs = "SD1_DATA_3", "GPIO63";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad37: PAD_GPIO_0_CFG {
+ index = <37>;
+ funcs = "ARM_JTAG_TRSTN", "GPIO0", "AC_I2S_DO", "DW_I2S_DO",
+ "SSI1_CLK", "SSI2_CLK", "ACIP_ADDAT", "PWM6",
+ "TEST_O_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad38: PAD_GPIO_1_CFG {
+ index = <38>;
+ funcs = "ARM_JTAG_TDO", "GPIO1", "AC_I2S_DI", "DW_I2S_DI",
+ "SSI1_CSN_0", "SSI2_CSN_0", "ACIP_DADAT", "PWM7",
+ "TEST_O_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad39: PAD_GPIO_2_CFG {
+ index = <39>;
+ funcs = "ARM_JTAG_TDI", "GPIO2", "AC_I2S_CLK", "DW_I2S_CLK",
+ "SSI1_TXD", "SSI2_TXD", "ACIP_ADBCLK", "PWM8",
+ "TEST_O_INT_SMI_MDIO_O";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad40: PAD_GPIO_3_CFG {
+ index = <40>;
+ funcs = "ARM_JTAG_TCK", "GPIO3", "AC_I2S_WS", "DW_I2S_WS",
+ "SSI1_RXD", "SSI2_RXD", "ACIP_ADLRC", "PWM9",
+ "TEST_I_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad41: PAD_GPIO_4_CFG {
+ index = <41>;
+ funcs = "ARM_JTAG_TMS", "GPIO4", "AC_MCLK", "USB_PWREN",
+ "SD1_CD", "TEST_I_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad42: PAD_SSI0_CLK_CFG {
+ index = <42>;
+ funcs = "SSI0_CLK", "GPIO5", "", "", "SD1_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad43: PAD_SSI0_CSN_0_CFG {
+ index = <43>;
+ funcs = "SSI0_CSN_0", "GPIO6", "", "", "SD1_CMD_RSP";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad44: PAD_SSI0_TXD_CFG {
+ index = <44>;
+ funcs = "SSI0_TXD", "GPIO7", "", "", "SD1_DATA_0";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad45: PAD_SSI0_RXD_CFG {
+ index = <45>;
+ funcs = "SSI0_RXD", "GPIO8", "", "", "SD1_DATA_1";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad46: PAD_SSI0_D2_CFG {
+ index = <46>;
+ funcs = "SSI0_D2", "GPIO9", "UART1_TX", "I2C1_SCL",
+ "SD1_DATA_2";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad47: PAD_SSI0_D3_CFG {
+ index = <47>;
+ funcs = "SSI0_D3", "GPIO10", "UART1_RX", "I2C1_SDA",
+ "SD1_DATA_3";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad48: PAD_SSI1_CLK_CFG {
+ index = <48>;
+ funcs = "SSI1_CLK", "GPIO11", "SSI2_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad49: PAD_SSI1_CSN_0_CFG {
+ index = <49>;
+ funcs = "SSI1_CSN_0", "GPIO14", "SSI2_CSN_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad50: PAD_SSI1_TXD_CFG {
+ index = <50>;
+ funcs = "SSI1_TXD", "GPIO15", "SSI2_TXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad51: PAD_SSI1_RXD_CFG {
+ index = <51>;
+ funcs = "SSI1_RXD", "GPIO16", "SSI2_RXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad52: PAD_SD0_CD_CFG {
+ index = <52>;
+ funcs = "SD0_CD", "GPIO17", "", "ARC_JTAG_TRSTN",
+ "PAE_JTAG_TRSTN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad53: PAD_SD0_CLK_CFG {
+ index = <53>;
+ funcs = "SD0_CLK", "GPIO18", "SSI1_CLK", "ARC_JTAG_TDO",
+ "PAE_JTAG_TDO";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad54: PAD_SD0_CMD_RSP_CFG {
+ index = <54>;
+ funcs = "SD0_CMD_RSP", "GPIO19", "SSI1_TXD", "ARC_JTAG_TDI",
+ "PAE_JTAG_TDI";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad55: PAD_SD0_DATA_0_CFG {
+ index = <55>;
+ funcs = "SD0_DATA_0", "GPIO20", "SSI1_RXD", "ARC_JTAG_TCK",
+ "PAE_JTAG_TCK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad56: PAD_SD0_DATA_1_CFG {
+ index = <56>;
+ funcs = "SD0_DATA_1", "GPIO21", "SSI1_CSN_0", "ARC_JTAG_TMS",
+ "PAE_JTAG_TMS";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad57: PAD_SD0_DATA_2_CFG {
+ index = <57>;
+ funcs = "SD0_DATA_2", "GPIO22", "", "UART2_TX", "I2C2_SCL", "",
+ "ACIP_DABCLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad58: PAD_SD0_DATA_3_CFG {
+ index = <58>;
+ funcs = "SD0_DATA_3", "GPIO23", "SSI1_CSN_0", "UART2_RX",
+ "I2C2_SDA", "", "ACIP_DALRC";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad59: PAD_SADC_XAIN0_CFG {
+ index = <59>;
+ funcs = "SADC_XAIN0", "GPIO26";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad60: PAD_SADC_XAIN1_CFG {
+ index = <60>;
+ funcs = "SADC_XAIN1", "GPIO27";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad61: PAD_SADC_XAIN2_CFG {
+ index = <61>;
+ funcs = "SADC_XAIN2", "GPIO24";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad62: PAD_SADC_XAIN3_CFG {
+ index = <62>;
+ funcs = "SADC_XAIN3", "GPIO25";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad63: PAD_GPIO_28_CFG {
+ index = <63>;
+ funcs = "GPIO28", "", "ETH_LINK_ACT", "PWM10",
+ "USB_DBG_CLK", "SD1_CD", "TEST_O_INT_RMII_TXEN",
+ "MAC_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad64: PAD_GPIO_29_CFG {
+ index = <64>;
+ funcs = "GPIO29", "", "ETH_LINK_STA", "PWM11", "RTC_CLK",
+ "ETH_LINK_SPD", "TEST_O_INT_SMI_MDIO_OE",
+ "MAC_MDIO";
+ pupd = <0>;
+ ds = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/fh8858v210.dts b/arch/arm/boot/dts/fh8858v210.dts
new file mode 100644
index 00000000..5a16fce3
--- /dev/null
+++ b/arch/arm/boot/dts/fh8858v210.dts
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2017 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "skeleton.dtsi"
+/include/ "fh8858v210_pinctrl.dtsi"
+/ {
+
+
+ model = "FULLHAN FH8858V210";
+ compatible = "fh,fh8858v210";
+ interrupt-parent = <&intc>;
+ aliases {
+ i2c0 = &i2cbus0;
+ i2c1 = &i2cbus1;
+ i2c2 = &i2cbus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ ttyS0 = &serial0;
+ ttyS1 = &serial1;
+ ttyS2 = &serial2;
+ };
+
+ cpus {
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,arm1176jzf-s";
+ };
+ };
+
+ chosen {
+ bootargs = "coherent_pool=2M";
+ };
+
+ intc: interrupt-controller@E0200000 {
+ compatible = "fh,fh-intc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0xE0200000 0x1000>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pmu@f0000000 {
+ compatible = "fh,fh-pmu";
+ reg = <0xf0000000 0x2100>;
+ SWRST_MAIN_CTRL = <0x40>;
+ };
+ timer0: timer@f0c00000 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00000 0x14>;
+ };
+
+ timer1: timer@f0c00014 {
+ compatible = "fh,fh-timer";
+ interrupts = <3>;
+ clock-frequency = <1000000>;
+ reg = <0xf0c00014 0x14>;
+ };
+
+ gpio0: gpio@f0300000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf0300000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <26>;
+ id = <0>;
+ ngpio = <32>;
+ base = <0>;
+ };
+
+ gpio1: gpio@f4000000 {
+ compatible = "fh,fh-gpio";
+ reg = <0xf4000000 0x1000>;
+ #gpio_controller;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ interrupts = <40>;
+ id = <1>;
+ ngpio = <32>;
+ base = <32>;
+ };
+
+ fhdma0: dma@e0300000 {
+ compatible = "fh,fh-axi-dmac";
+ reg = <0xe0300000 0x1000>;
+ interrupts = <23>;
+ chan_allocation_order = <0>;
+ chan_priority = <1>;
+ block_size = <0x800>;
+ data_width = <2 0 0 0>;
+ clocks = <&ahb_clk>;
+ };
+
+ aes: aes@0xe8200000 {
+ compatible = "fh,fh-aes";
+ reg = <0xe8200000 0x1000>;
+ interrupts = <16>;
+ };
+ rtc: rtc@f1500000 {
+ compatible = "fh,fh_rtc";
+ reg = <0xf1500000 0x1000>;
+ interrupts = <33>;
+ clocks = <&rtc_hclk_gate>;
+ lut_cof = <71>;
+ lut_offset = <0xf6>;
+ tsensor_cp_default_out = <0x9cc>;
+ };
+ sadc: sadc@f1200000 {
+ compatible = "fh,fh-sadc";
+ reg = <0xf1200000 0x1000>;
+ interrupts = <20>;
+ ref-vol = <1800>;
+ active-bit = <0xfff>;
+ };
+ efuse: efuse@0xf1600000 {
+ compatible = "fh,fh-efuse";
+ reg = <0xf1600000 0x1000>;
+ key_switch = "enable";
+ indep_power = "enable";
+ };
+ fh_perf: fh_perf@0xf0002018 {
+ compatible = "fh,fh-perf";
+ reg = <0xf0000000 0x4000>;
+ interrupts = < 5 >;
+
+ };
+ spi_bus0: spi@f0500000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0500000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <6>;
+ cs1_gpio = <55>;
+ dma_enable = "disable";
+ swap_support = "enable";
+ rx_hs_no = <4>;
+ tx_hs_no = <5>;
+ bus_no = <0>;
+ multi_wire_size = <2>;
+ clk_name = "spi0_clk";
+ rx_dma_channel = <0>;
+ tx_dma_channel = <1>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <28>;
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fh,m25p80";
+ spi-max-frequency = <50000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ reg = <0x0 0>; //first value means which slave bind to the master. 0 means chip 0. 1 means chip 1
+ partition@0 {
+ reg = <0x0 0x40000>;
+ label = "bootstrap";
+ };
+ partition@40000 {
+ reg = <0x40000 0x10000>;
+ label = "uboot-env";
+ };
+ partition@50000 {
+ reg = <0x50000 0x30000>;
+ label = "uboot";
+ };
+ partition@80000 {
+ reg = <0x80000 0x400000>;
+ label = "kernel";
+ };
+ partition@480000 {
+ reg = <0x480000 0x80000>;
+ label = "rootfs";
+ };
+ partition@500000 {
+ reg = <0x500000 0x300000>;
+ label = "app";
+ };
+
+ };
+ spidev0: spi@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ spi_bus1: spi@f0600000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+ compatible = "fh,fh-spi";
+ reg = <0xf0600000 0x4000>;
+ clk_in = <100000000>;
+ clock_source = <100000000>;
+ clock_source_num = <1>;
+ num-cs = <2>;
+ cs0_gpio = <14>;
+ cs1_gpio = <57>;
+ dma_enable = "disable";
+ swap_support = "disable";
+ rx_hs_no = <2>;
+ tx_hs_no = <3>;
+ bus_no = <1>;
+ clk_name = "spi1_clk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ increase_support = "disable";
+ data_field_size = <0x1000>;
+ data_reg_offset = <0x1000>;
+ dma_protctl_enable = "disable";
+ dma_protctl_data = <6>;
+ dma_master_sel_enable = "disable";
+ dma_master_ctl_sel = <0>;
+ dma_master_mem_sel = <0>;
+ spidma_xfer_mode = "rx_only";
+ interrupts = <21>;
+ spidev1: spi@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x0 0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev2: spi@2 {
+ compatible = "rohm,dh2228fv";
+ reg = <0x1 0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
+ fhdwi2s: i2s@f0900000 {
+ compatible = "fh,fh-dw_i2s";
+ reg = <0xf0900000 0x1000>;
+ interrupts = <25>;
+ clocks = <&i2s_clk>, <&ac_clk>;
+ clock-names = "i2s_clk", "acodec_mclk";
+ rx_dma_channel = <2>;
+ tx_dma_channel = <3>;
+ dma_master = <0>;
+ dma_rx_hs_num = <10>;
+ dma_tx_hs_num = <11>;
+ };
+
+ fhacw: acw@f0a00000 {
+ compatible = "fh,fh-acw";
+ reg = <0xf0a00000 0x1000>;
+ interrupts = <19>;
+ clocks = <&ac_clk>;
+ clock-names = "ac_clk";
+ rx_dma_channel = <4>;
+ tx_dma_channel = <5>;
+ dma_master = <0>;
+ dma_rx_hs_num = <0>;
+ dma_tx_hs_num = <1>;
+ };
+
+ pwm: pwm@f0400000{
+ compatible = "fh,fh-pwm";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <36>;
+ npwm = <14>;
+ };
+ serial0: serial@f0700000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0700000 0x1000>;
+ interrupts = <30>;
+ clock-frequency = <16666667>;
+ fifo-size = <32>;
+ };
+ serial1: serial@f0800000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf0800000 0x1000>;
+ interrupts = <31>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ serial2: serial@f1300000 {
+ compatible = "fh,fh-serial";
+ reg = <0xf1300000 0x1000>;
+ interrupts = <41>;
+ clock-frequency = <16666667>;
+ fifo-size = <64>;
+ };
+ gmac0: gmac@e0600000 {
+ compatible = "fh,fh-gmac";
+ reg = <0xe0600000 0x2000>;
+ interrupts = <44>;
+ phyreset-gpio = <29>;
+ };
+ sdc0: sdc0@e2000000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2000000 0x4000>;
+ interrupts = <42>;
+ id = <0>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <0>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <0>;
+ };
+ sdc1: sdc1@e2200000 {
+ compatible = "fh,fh-sdc";
+ reg = <0xe2200000 0x4000>;
+ interrupts = <43>;
+ id = <1>;
+ buswidth = <4>;
+ wp-fixed = <1>;
+ cd-fixed = <1>;
+ drv-degree = <8>;
+ sam-degree = <0>;
+ scan-mux = <2>;
+ };
+ wdt: wdt@f0d00000{
+ compatible = "fh,fh-wdt";
+ reg = <0xf0d00000 0x1000>;
+ interrupts = <2>;
+ mode = <1>;
+ };
+ i2cbus0: i2c@f0200000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0200000 0x2000>;
+ interrupts = <11>;
+ };
+ i2cbus1: i2c@f0b00000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xf0b00000 0x2000>;
+ interrupts = <12>;
+ };
+ i2cbus2: i2c@0xF0100000 {
+ compatible = "fh,fh-i2c";
+ reg = <0xF0100000 0x2000>;
+ interrupts = <46>;
+ };
+ clocks: src_clk@0xf0000000{
+ compatible = "fh,fh-clk";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf0000000 0x80>;
+ ranges;
+
+ osc_clk: mxtal@24M {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc_clk";
+ };
+
+ pll_ddr_rclk: pllddrr{
+ #clock-cells = <0>;
+ compatible = "fh pll-ddr-rclk";
+ reg = <0xf0000010 0x4>,<0xf0000018 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_ddr_rclk";
+ };
+ pll_cpu_pclk: pllcpup{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-pclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_pclk";
+ };
+ pll_cpu_rclk: pllcpur{
+ #clock-cells = <0>;
+ compatible = "fh pll-cpu-rclk";
+ reg = <0xf0000014 0x4>,<0xf000006c 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_cpu_rclk";
+ };
+ pll_sys_pclk: pllsysp{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-pclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f0000>;
+ divcop = <0xf00>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_pclk";
+ };
+ pll_sys_rclk: pllsysr{
+ #clock-cells = <0>;
+ compatible = "fh pll-sys-rclk";
+ reg = <0xf0000064 0x4>,<0xf0000068 0x4>;
+ m = <0x7f>;
+ n = <0x1f00>;
+ pr = <0x3f000000>;
+ divcop = <0xf000>;
+ clocks = <&osc_clk>;
+ clock-output-names = "pll_sys_rclk";
+ };
+ sysp_div12_clk: syspdiv12clk{
+ #clock-cells = <0>;
+ compatible = "fh sysp-div12-clk";
+ reg = <0xf0000038 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sysp_div12_clk";
+ };
+ ddr_clk: ddrclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ddr-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clocks = <&pll_ddr_rclk>;
+ clock-output-names = "ddr_clk";
+ };
+ arm_clk: armclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arm-clk";
+ reg = <0x0 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_pclk>;
+ clock-output-names = "arm_clk";
+ };
+ arc_clk: arcclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-arc-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ gate = <0x4000000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_cpu_rclk>;
+ clock-output-names = "arc_clk";
+ };
+ ahb_clk: ahbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ahb-clk";
+ reg = <0xf0000024 0x4>,<0x0 0x4>,<0xf000000c 0x4>;
+ div = <0xf0000>;
+ mux = <0x1>;
+ clocks = <&osc_clk>,<&pll_sys_pclk>;
+ clock-output-names = "ahb_clk";
+ };
+ isp_aclk: ispaclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispa-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00>;
+ gate = <0x1>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "isp_aclk";
+ };
+ ispb_aclk: ispbclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ispb-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "ispb_aclk";
+ };
+ vpu_clk: vpuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80000000>;
+ clocks = <&isp_aclk>;
+ clock-output-names = "vpu_clk";
+ };
+ pix_clk: pixclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-pix-clk";
+ reg = <0xf000002c 0x4>,<0x0 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "pix_clk";
+ };
+ jpeg_clk: jpegclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-clk";
+ reg = <0xf000005c 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "jpeg_clk";
+ };
+ bgm_clk: bgmclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf00000>;
+ gate = <0x40000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "bgm_clk";
+ };
+ jpeg_adapt_clk: jpegadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-jpeg-adapt-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2>;
+ clocks = <&jpeg_clk>;
+ clock-output-names = "jpeg_adapt_clk";
+ };
+ spi0_clk: spi0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x80>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi0_clk";
+ };
+ sdc0_clk: sdc0clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf00>;
+ gate = <0x200>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc0_clk";
+ };
+ spi2_clk: spi2clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi2-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000>;
+ gate = <0x2>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi2_clk";
+ };
+ spi1_clk: spi1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-spi1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x100>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "spi1_clk";
+ };
+ sdc1_clk: sdc1clk{
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk";
+ reg = <0xf0000030 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ prediv =<8>;
+ div = <0xf000000>;
+ gate = <0x400>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "sdc1_clk";
+ };
+ veu_clk: veuclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-clk";
+ reg = <0xf0000024 0x4>,<0xf000001c 0x4>,<0xf000000c 0x4>;
+ div = <0x7000000>;
+ gate = <0x10>;
+ mux = <0x4>;
+ clocks = <&pll_sys_pclk>,<&pll_sys_rclk>;
+ clock-output-names = "veu_clk";
+ };
+ veu_adapt_clk: veuadaptclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-adapt-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clocks = <&veu_clk>;
+ clock-output-names = "veu_adapt_clk";
+ };
+ cis_clk_out: cisclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-cis-clk-out";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x800000>;
+ clocks = <&pll_sys_pclk>;
+ clock-output-names = "cis_clk_out";
+ };
+ eth_clk: ethclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-eth-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xf000000>;
+ gate = <0x2000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "eth_clk";
+ };
+ eth_rmii_clk: ethrmiiclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ethrmii-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "eth_rmii_clk";
+ };
+ i2c0_clk: i2c0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f0000>;
+ gate = <0x1000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c0_clk";
+ };
+
+ i2c1_clk: i2c1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x8000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c1_clk";
+ };
+ i2c2_clk: i2c2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-i2c2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x00000008>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "i2c2_clk";
+ };
+
+ uart0_clk: uart0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart0-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f>;
+ gate = <0x2000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart0_clk";
+ };
+
+ uart1_clk: uart1clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart1-clk";
+ reg = <0xf0000034 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1f00>;
+ gate = <0x4000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart1_clk";
+ };
+ uart2_clk: uart2clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-uart2-clk";
+ reg = <0xf000005c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f>;
+ gate = <0x8000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "uart2_clk";
+ };
+ pwm_clk: pwmclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pwm-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff>;
+ gate = <0x10000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pwm_clk";
+ };
+ efuse_clk: efuseclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-efuse-clk";
+ reg = <0xf0000028 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f000000>;
+ gate = <0x200000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "efuse_clk";
+ };
+ pts_clk: ptsclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-pts-clk";
+ reg = <0xf000002c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x1ff>;
+ gate = <0x80000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "pts_clk";
+ };
+ tmr0_clk: tmr0clk {
+ #clock-cells = <0>;
+ compatible = "fh fh-tmr0-clk";
+ reg = <0xf0000038 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0xff0000>;
+ gate = <0x20000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "tmr0_clk";
+ };
+
+ sadc_clk: sadcclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sadc-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x7f0000>;
+ gate = <0x4000000>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "sadc_clk";
+ };
+ gpio0_dbclk: gpio0dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff>;
+ gate = <0x8000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio0_dbclk";
+ };
+ gpio1_dbclk: gpio1dbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-dbclk";
+ reg = <0xf0000060 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ div = <0x7fff0000>;
+ gate = <0x80000000>;
+ prediv = <100>;
+ clocks = <&sysp_div12_clk>;
+ clock-output-names = "gpio1_dbclk";
+ };
+ wdt_clk: wdtclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-wdt-clk";
+ reg = <0xf0000038 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ div = <0xff00>;
+ gate = <0x8000000>;
+ clocks = <&ahb_clk>;
+ clock-output-names = "wdt_clk";
+ };
+ ac_clk: acclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-ac-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f>;
+ gate = <0x800>;
+ clocks = <&osc_clk>;
+ clock-output-names = "ac_clk";
+ };
+ i2s_clk: i2sclk{
+ #clock-cells = <0>;
+ compatible = "fh fh-i2s-clk";
+ reg = <0xf000003c 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ div = <0x3f00>;
+ gate = <0x1000000>;
+ clocks = <&ac_clk>;
+ clock-output-names = "i2s_clk";
+ };
+ mipi_dphy_clk: mipidphyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-dphy-clk";
+ reg = <0x0 0x4>,<0xf000001c 0x4>,<0x0 0x4>;
+ gate = <0x100000>;
+ clock-output-names = "mipi_dphy_clk";
+ };
+ mipi_wrap_gate: mipiwrapclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipi-wrap-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "mipi_wrap_gate";
+ };
+ rtc_hclk_gate: rtchclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-rtc-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "rtc_hclk_gate";
+ };
+ emac_hclk_gate: emachclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-emac-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "emac_hclk_gate";
+ };
+ usb_clk: usbclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-usb-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "usb_clk";
+ };
+ aes_hclk_gate: aeshclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-aes-hclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x80>;
+ clock-output-names = "aes_hclk_gate";
+ };
+ ephy_clk_gate: ephyclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-ephy-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x1>;
+ clock-output-names = "ephy_clk_gate";
+ };
+ sdc0_clk8x_gate: sdc08xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc08x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x4>;
+ clock-output-names = "sdc0_clk8x_gate";
+ };
+ sdc1_clk8x_gate: sdc18xclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc18x-clk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x8>;
+ clock-output-names = "sdc1_clk8x_gate";
+ };
+ mipic_pclk_gate: mipicpclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-mipic-pclk";
+ reg = <0x0 0x4>,<0xf0000020 0x4>,<0x0 0x4>;
+ gate = <0x10>;
+ clock-output-names = "mipic_pclk_gate";
+ };
+ gpio0_pclk_gate: gpio0pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio0-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x4000>;
+ clock-output-names = "gpio0_pclk_gate";
+ };
+ gpio1_pclk_gate: gpio1pclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-gpio1-pclk";
+ reg = <0x0 0x4>,<0xf0000060 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "gpio1_pclk_gate";
+ };
+ isp_hclk_gate: isphclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-isp-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x1000000>;
+ clock-output-names = "isp_hclk_gate";
+ };
+ veu_hclk_gate: veuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-veu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x2000000>;
+ clock-output-names = "veu_hclk_gate";
+ };
+ bgm_hclk_gate: bgmhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-bgm-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x4000000>;
+ clock-output-names = "bgm_hclk_gate";
+ };
+ adapt_hclk_gate: adapthclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-adapt-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x8000000>;
+ clock-output-names = "adapt_hclk_gate";
+ };
+ jpg_hclk_gate: jpghclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x10000000>;
+ clock-output-names = "jpg_hclk_gate";
+ };
+ jpg_adapt_gate: jpgadaptclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-jpg-adapt-clk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x20000000>;
+ clock-output-names = "jpg_adapt_gate";
+ };
+ vpu_hclk_gate: vpuhclk {
+ #clock-cells = <0>;
+ compatible = "fh fh-vpu-hclk";
+ reg = <0x0 0x4>,<0xf000005c 0x4>,<0x0 0x4>;
+ gate = <0x40000000>;
+ clock-output-names = "vpu_hclk_gate";
+ };
+ sdc0_clk_sample: sdc0clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf0000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_sample";
+ };
+ sdc0_clk_drv: sdc0clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc0-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00000>;
+ clocks = <&sdc0_clk>;
+ clock-output-names = "sdc0_clk_drv";
+ };
+
+ sdc1_clk_sample: sdc1clksample {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_sample";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf00>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_sample";
+ };
+
+ sdc1_clk_drv: sdc1clkdrv {
+ #clock-cells = <0>;
+ compatible = "fh fh-sdc1-clk_drv";
+ reg = <0xf0000020 0x4>;
+ mux = <0xf000>;
+ clocks = <&sdc1_clk>;
+ clock-output-names = "sdc1_clk_drv";
+ };
+ };
+ };
+
+ usb_otg@e0700000 {
+ compatible = "fh_usb";
+ reg = <0xe0700000 100000>;
+ interrupts = <39>;
+ clocks = <&usb_clk>;
+ dr_mode = "host";
+ vbus_pwren = <47>;
+ clock-names = "otg";
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
+ };
+
+ usb2_phy: usbphy {
+ compatible = "fh,fh-usb2-phy";
+ #phy-cells = <0>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm/boot/dts/fh8858v210_pinctrl.dtsi b/arch/arm/boot/dts/fh8858v210_pinctrl.dtsi
new file mode 100644
index 00000000..731caa02
--- /dev/null
+++ b/arch/arm/boot/dts/fh8858v210_pinctrl.dtsi
@@ -0,0 +1,2379 @@
+/*
+ * Copyright (C) 2020 Fullhan Micorelectonics Co.,Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ #define PUPD_NONE (0)
+ #define PUPD_UP (1)
+ #define PUPD_DOWN (2)
+*/
+
+/ {
+ pinctrl: pinctrl@f0000080 {
+ compatible = "fh,fh-pinctrl";
+ reg = <0xf0000080 0x104>;
+ pad-num = <65>;
+ max-mux = <9>;
+ pinctrl-names = "default";
+ pinctrl-0 = <
+ &pinctrl_AC_MCLK
+ &pinctrl_ETH
+ &pinctrl_I2C0
+ &pinctrl_PWM2
+ &pinctrl_PWM3
+ &pinctrl_PWM4
+ &pinctrl_PWM5
+ &pinctrl_PWM6
+ &pinctrl_PWM7
+ &pinctrl_PWM8
+ &pinctrl_PWM9
+ &pinctrl_SADC_XAIN0
+ &pinctrl_SADC_XAIN1
+ &pinctrl_SADC_XAIN2
+ &pinctrl_SADC_XAIN3
+ &pinctrl_SD0_NO_WP
+ &pinctrl_SD1_NO_WP
+ &pinctrl_SENSOR_CLK
+ &pinctrl_SSI0_4BIT
+ &pinctrl_SSI1
+ &pinctrl_UART0
+ &pinctrl_UART1
+ &pinctrl_GPIO13
+ &pinctrl_GPIO28
+ &pinctrl_GPIO29
+ &pinctrl_GPIO30
+ &pinctrl_GPIO31
+ &pinctrl_GPIO32
+ &pinctrl_GPIO43
+ &pinctrl_GPIO44
+ &pinctrl_GPIO47
+ &pinctrl_GPIO48
+ &pinctrl_GPIO49
+ &pinctrl_GPIO50
+ &pinctrl_GPIO51
+ &pinctrl_GPIO52
+ &pinctrl_GPIO53
+ &pinctrl_GPIO54
+ &pinctrl_GPIO55
+ &pinctrl_GPIO56
+
+ &pinctrl_GPIO45
+ &pinctrl_GPIO46
+ >;
+ pinctrl_groups {
+ pinctrl_ACI2S: ACI2S {
+ fh,pins = <
+ &mux_AC_I2S_CLK 0
+ &mux_AC_I2S_DI 0
+ &mux_AC_I2S_DO 0
+ &mux_AC_I2S_WS 0
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_AC_MCLK: AC_MCLK {
+ fh,pins = <
+ &mux_AC_MCLK 0
+ >;
+ };
+ pinctrl_ARCJTAG: ARCJTAG {
+ fh,pins = <
+ &mux_ARC_JTAG_TCK 0
+ &mux_ARC_JTAG_TDI 0
+ &mux_ARC_JTAG_TDO 0
+ &mux_ARC_JTAG_TMS 0
+ &mux_ARC_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_ARMJTAG: ARMJTAG {
+ fh,pins = <
+ &mux_ARM_JTAG_TCK 0
+ &mux_ARM_JTAG_TDI 0
+ &mux_ARM_JTAG_TDO 0
+ &mux_ARM_JTAG_TMS 0
+ &mux_ARM_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_DWI2S: DWI2S {
+ fh,pins = <
+ &mux_DW_I2S_CLK 0
+ &mux_DW_I2S_DI 0
+ &mux_DW_I2S_DO 0
+ &mux_DW_I2S_WS 0
+ >;
+ };
+ pinctrl_ETH: ETH {
+ fh,pins = <
+ &mux_ETH_LINK_ACT 1
+ &mux_ETH_LINK_STA 1
+ >;
+ };
+ pinctrl_I2C0: I2C0 {
+ fh,pins = <
+ &mux_I2C0_SCL 0
+ &mux_I2C0_SDA 0
+ >;
+ };
+ pinctrl_I2C1: I2C1 {
+ fh,pins = <
+ &mux_I2C1_SCL 2
+ &mux_I2C1_SDA 2
+ >;
+ };
+ pinctrl_I2C2: I2C2 {
+ fh,pins = <
+ &mux_I2C2_SCL 1
+ &mux_I2C2_SDA 1
+ >;
+ };
+ pinctrl_PAEJTAG: PAEJTAG {
+ fh,pins = <
+ &mux_PAE_JTAG_TCK 0
+ &mux_PAE_JTAG_TDI 0
+ &mux_PAE_JTAG_TDO 0
+ &mux_PAE_JTAG_TMS 0
+ &mux_PAE_JTAG_TRSTN 0
+ >;
+ };
+ pinctrl_PWM0: PWM0 {
+ fh,pins = <
+ &mux_PWM0 0
+ >;
+ };
+ pinctrl_PWM1: PWM1 {
+ fh,pins = <
+ &mux_PWM1 0
+ >;
+ };
+ pinctrl_PWM10: PWM10 {
+ fh,pins = <
+ &mux_PWM10 0
+ >;
+ };
+ pinctrl_PWM11: PWM11 {
+ fh,pins = <
+ &mux_PWM11 0
+ >;
+ };
+ pinctrl_PWM2: PWM2 {
+ fh,pins = <
+ &mux_PWM2 0
+ >;
+ };
+ pinctrl_PWM3: PWM3 {
+ fh,pins = <
+ &mux_PWM3 0
+ >;
+ };
+ pinctrl_PWM4: PWM4 {
+ fh,pins = <
+ &mux_PWM4 0
+ >;
+ };
+ pinctrl_PWM5: PWM5 {
+ fh,pins = <
+ &mux_PWM5 0
+ >;
+ };
+ pinctrl_PWM6: PWM6 {
+ fh,pins = <
+ &mux_PWM6 1
+ >;
+ };
+ pinctrl_PWM7: PWM7 {
+ fh,pins = <
+ &mux_PWM7 1
+ >;
+ };
+ pinctrl_PWM8: PWM8 {
+ fh,pins = <
+ &mux_PWM8 1
+ >;
+ };
+ pinctrl_PWM9: PWM9 {
+ fh,pins = <
+ &mux_PWM9 1
+ >;
+ };
+ pinctrl_RMII: RMII {
+ fh,pins = <
+ &mux_MAC_MDC 0
+ &mux_MAC_MDIO 0
+ &mux_MAC_REF_CLK 0
+ &mux_MAC_RMII_CLK 0
+ &mux_MAC_RXDV 0
+ &mux_MAC_RXD_0 0
+ &mux_MAC_RXD_1 0
+ &mux_MAC_TXD_0 0
+ &mux_MAC_TXD_1 0
+ &mux_MAC_TXEN 0
+ >;
+ };
+ pinctrl_RTC: RTC {
+ fh,pins = <
+ &mux_RTC_CLK 0
+ >;
+ };
+ pinctrl_SADC_XAIN0: SADC_XAIN0 {
+ fh,pins = <
+ &mux_SADC_XAIN0 0
+ >;
+ };
+ pinctrl_SADC_XAIN1: SADC_XAIN1 {
+ fh,pins = <
+ &mux_SADC_XAIN1 0
+ >;
+ };
+ pinctrl_SADC_XAIN2: SADC_XAIN2 {
+ fh,pins = <
+ &mux_SADC_XAIN2 0
+ >;
+ };
+ pinctrl_SADC_XAIN3: SADC_XAIN3 {
+ fh,pins = <
+ &mux_SADC_XAIN3 0
+ >;
+ };
+ pinctrl_SD0: SD0 {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_1BIT_NO_WP: SD0_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ >;
+ };
+ pinctrl_SD0_NO_WP: SD0_NO_WP {
+ fh,pins = <
+ &mux_SD0_CD 0
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD0_WIFI: SD0_WIFI {
+ fh,pins = <
+ &mux_SD0_CLK 0
+ &mux_SD0_CMD_RSP 0
+ &mux_SD0_DATA_0 0
+ &mux_SD0_DATA_1 0
+ &mux_SD0_DATA_2 0
+ &mux_SD0_DATA_3 0
+ >;
+ };
+ pinctrl_SD1: SD1 {
+ fh,pins = <
+ &mux_SD1_CD 2
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ &mux_SD1_DATA_1 2
+ &mux_SD1_DATA_2 2
+ &mux_SD1_DATA_3 2
+ >;
+ };
+ pinctrl_SD1_1BIT_NO_WP: SD1_1BIT_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 2
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ >;
+ };
+ pinctrl_SD1_NO_WP: SD1_NO_WP {
+ fh,pins = <
+ &mux_SD1_CD 2
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ &mux_SD1_DATA_1 2
+ &mux_SD1_DATA_2 2
+ &mux_SD1_DATA_3 2
+ >;
+ };
+ pinctrl_SD1_WIFI: SD1_WIFI {
+ fh,pins = <
+ &mux_SD1_CLK 2
+ &mux_SD1_CMD_RSP 2
+ &mux_SD1_DATA_0 2
+ &mux_SD1_DATA_1 2
+ &mux_SD1_DATA_2 2
+ &mux_SD1_DATA_3 2
+ >;
+ };
+ pinctrl_SENSOR_CLK: SENSOR_CLK {
+ fh,pins = <
+ &mux_SENSOR_CLK 0
+ >;
+ };
+ pinctrl_SSI0: SSI0 {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI0_4BIT: SSI0_4BIT {
+ fh,pins = <
+ &mux_GPIO6 0
+ &mux_SSI0_CLK 0
+ &mux_SSI0_D2 0
+ &mux_SSI0_D3 0
+ &mux_SSI0_RXD 0
+ &mux_SSI0_TXD 0
+ >;
+ };
+ pinctrl_SSI1: SSI1 {
+ fh,pins = <
+ &mux_GPIO14 0
+ &mux_SSI1_CLK 2
+ &mux_SSI1_RXD 2
+ &mux_SSI1_TXD 2
+ >;
+ };
+ pinctrl_SSI2: SSI2 {
+ fh,pins = <
+ &mux_SSI2_CLK 1
+ &mux_SSI2_CSN_0 1
+ &mux_SSI2_RXD 1
+ &mux_SSI2_TXD 1
+ >;
+ };
+ pinctrl_UART0: UART0 {
+ fh,pins = <
+ &mux_UART0_RX 0
+ &mux_UART0_TX 0
+ >;
+ };
+ pinctrl_UART1: UART1 {
+ fh,pins = <
+ &mux_UART1_RX 0
+ &mux_UART1_TX 0
+ >;
+ };
+ pinctrl_UART2: UART2 {
+ fh,pins = <
+ &mux_UART2_RX 0
+ &mux_UART2_TX 0
+ >;
+ };
+ pinctrl_USB: USB {
+ fh,pins = <
+ &mux_USB_PWREN 0
+ >;
+ };
+ pinctrl_GPIO0: GPIO0 {
+ fh,pins = <
+ &mux_GPIO0 0
+ >;
+ };
+ pinctrl_GPIO1: GPIO1 {
+ fh,pins = <
+ &mux_GPIO1 0
+ >;
+ };
+ pinctrl_GPIO2: GPIO2 {
+ fh,pins = <
+ &mux_GPIO2 0
+ >;
+ };
+ pinctrl_GPIO3: GPIO3 {
+ fh,pins = <
+ &mux_GPIO3 0
+ >;
+ };
+ pinctrl_GPIO4: GPIO4 {
+ fh,pins = <
+ &mux_GPIO4 0
+ >;
+ };
+ pinctrl_GPIO5: GPIO5 {
+ fh,pins = <
+ &mux_GPIO5 0
+ >;
+ };
+ pinctrl_GPIO6: GPIO6 {
+ fh,pins = <
+ &mux_GPIO6 0
+ >;
+ };
+ pinctrl_GPIO7: GPIO7 {
+ fh,pins = <
+ &mux_GPIO7 0
+ >;
+ };
+ pinctrl_GPIO8: GPIO8 {
+ fh,pins = <
+ &mux_GPIO8 0
+ >;
+ };
+ pinctrl_GPIO9: GPIO9 {
+ fh,pins = <
+ &mux_GPIO9 0
+ >;
+ };
+ pinctrl_GPIO10: GPIO10 {
+ fh,pins = <
+ &mux_GPIO10 0
+ >;
+ };
+ pinctrl_GPIO11: GPIO11 {
+ fh,pins = <
+ &mux_GPIO11 0
+ >;
+ };
+ pinctrl_GPIO12: GPIO12 {
+ fh,pins = <
+ &mux_GPIO12 0
+ >;
+ };
+ pinctrl_GPIO13: GPIO13 {
+ fh,pins = <
+ &mux_GPIO13 0
+ >;
+ };
+ pinctrl_GPIO14: GPIO14 {
+ fh,pins = <
+ &mux_GPIO14 0
+ >;
+ };
+ pinctrl_GPIO15: GPIO15 {
+ fh,pins = <
+ &mux_GPIO15 0
+ >;
+ };
+ pinctrl_GPIO16: GPIO16 {
+ fh,pins = <
+ &mux_GPIO16 0
+ >;
+ };
+ pinctrl_GPIO17: GPIO17 {
+ fh,pins = <
+ &mux_GPIO17 0
+ >;
+ };
+ pinctrl_GPIO18: GPIO18 {
+ fh,pins = <
+ &mux_GPIO18 0
+ >;
+ };
+ pinctrl_GPIO19: GPIO19 {
+ fh,pins = <
+ &mux_GPIO19 0
+ >;
+ };
+ pinctrl_GPIO20: GPIO20 {
+ fh,pins = <
+ &mux_GPIO20 0
+ >;
+ };
+ pinctrl_GPIO21: GPIO21 {
+ fh,pins = <
+ &mux_GPIO21 0
+ >;
+ };
+ pinctrl_GPIO22: GPIO22 {
+ fh,pins = <
+ &mux_GPIO22 0
+ >;
+ };
+ pinctrl_GPIO23: GPIO23 {
+ fh,pins = <
+ &mux_GPIO23 0
+ >;
+ };
+ pinctrl_GPIO24: GPIO24 {
+ fh,pins = <
+ &mux_GPIO24 0
+ >;
+ };
+ pinctrl_GPIO25: GPIO25 {
+ fh,pins = <
+ &mux_GPIO25 0
+ >;
+ };
+ pinctrl_GPIO26: GPIO26 {
+ fh,pins = <
+ &mux_GPIO26 0
+ >;
+ };
+ pinctrl_GPIO27: GPIO27 {
+ fh,pins = <
+ &mux_GPIO27 0
+ >;
+ };
+ pinctrl_GPIO28: GPIO28 {
+ fh,pins = <
+ &mux_GPIO28 0
+ >;
+ };
+ pinctrl_GPIO29: GPIO29 {
+ fh,pins = <
+ &mux_GPIO29 0
+ >;
+ };
+ pinctrl_GPIO30: GPIO30 {
+ fh,pins = <
+ &mux_GPIO30 0
+ >;
+ };
+ pinctrl_GPIO31: GPIO31 {
+ fh,pins = <
+ &mux_GPIO31 0
+ >;
+ };
+ pinctrl_GPIO32: GPIO32 {
+ fh,pins = <
+ &mux_GPIO32 0
+ >;
+ };
+ pinctrl_GPIO33: GPIO33 {
+ fh,pins = <
+ &mux_GPIO33 0
+ >;
+ };
+ pinctrl_GPIO34: GPIO34 {
+ fh,pins = <
+ &mux_GPIO34 0
+ >;
+ };
+ pinctrl_GPIO35: GPIO35 {
+ fh,pins = <
+ &mux_GPIO35 0
+ >;
+ };
+ pinctrl_GPIO36: GPIO36 {
+ fh,pins = <
+ &mux_GPIO36 0
+ >;
+ };
+ pinctrl_GPIO37: GPIO37 {
+ fh,pins = <
+ &mux_GPIO37 0
+ >;
+ };
+ pinctrl_GPIO38: GPIO38 {
+ fh,pins = <
+ &mux_GPIO38 0
+ >;
+ };
+ pinctrl_GPIO39: GPIO39 {
+ fh,pins = <
+ &mux_GPIO39 0
+ >;
+ };
+ pinctrl_GPIO40: GPIO40 {
+ fh,pins = <
+ &mux_GPIO40 0
+ >;
+ };
+ pinctrl_GPIO41: GPIO41 {
+ fh,pins = <
+ &mux_GPIO41 0
+ >;
+ };
+ pinctrl_GPIO42: GPIO42 {
+ fh,pins = <
+ &mux_GPIO42 0
+ >;
+ };
+ pinctrl_GPIO43: GPIO43 {
+ fh,pins = <
+ &mux_GPIO43 0
+ >;
+ };
+ pinctrl_GPIO44: GPIO44 {
+ fh,pins = <
+ &mux_GPIO44 0
+ >;
+ };
+ pinctrl_GPIO45: GPIO45 {
+ fh,pins = <
+ &mux_GPIO45 0
+ >;
+ };
+ pinctrl_GPIO46: GPIO46 {
+ fh,pins = <
+ &mux_GPIO46 0
+ >;
+ };
+ pinctrl_GPIO47: GPIO47 {
+ fh,pins = <
+ &mux_GPIO47 0
+ >;
+ };
+ pinctrl_GPIO48: GPIO48 {
+ fh,pins = <
+ &mux_GPIO48 0
+ >;
+ };
+ pinctrl_GPIO49: GPIO49 {
+ fh,pins = <
+ &mux_GPIO49 0
+ >;
+ };
+ pinctrl_GPIO50: GPIO50 {
+ fh,pins = <
+ &mux_GPIO50 0
+ >;
+ };
+ pinctrl_GPIO51: GPIO51 {
+ fh,pins = <
+ &mux_GPIO51 0
+ >;
+ };
+ pinctrl_GPIO52: GPIO52 {
+ fh,pins = <
+ &mux_GPIO52 0
+ >;
+ };
+ pinctrl_GPIO53: GPIO53 {
+ fh,pins = <
+ &mux_GPIO53 0
+ >;
+ };
+ pinctrl_GPIO54: GPIO54 {
+ fh,pins = <
+ &mux_GPIO54 0
+ >;
+ };
+ pinctrl_GPIO55: GPIO55 {
+ fh,pins = <
+ &mux_GPIO55 0
+ >;
+ };
+ pinctrl_GPIO56: GPIO56 {
+ fh,pins = <
+ &mux_GPIO56 0
+ >;
+ };
+ pinctrl_GPIO57: GPIO57 {
+ fh,pins = <
+ &mux_GPIO57 0
+ >;
+ };
+ pinctrl_GPIO58: GPIO58 {
+ fh,pins = <
+ &mux_GPIO58 0
+ >;
+ };
+ pinctrl_GPIO59: GPIO59 {
+ fh,pins = <
+ &mux_GPIO59 0
+ >;
+ };
+ pinctrl_GPIO60: GPIO60 {
+ fh,pins = <
+ &mux_GPIO60 0
+ >;
+ };
+ pinctrl_GPIO61: GPIO61 {
+ fh,pins = <
+ &mux_GPIO61 0
+ >;
+ };
+ pinctrl_GPIO62: GPIO62 {
+ fh,pins = <
+ &mux_GPIO62 0
+ >;
+ };
+ pinctrl_GPIO63: GPIO63 {
+ fh,pins = <
+ &mux_GPIO63 0
+ >;
+ };
+ pinctrl_SD1_EMMC: SD1_EMMC {
+ fh,pins = <
+ &mux_SD1_CD 3
+ &mux_SD1_CLK 3
+ &mux_SD1_CMD_RSP 3
+ &mux_SD1_DATA_0 3
+ &mux_SD1_DATA_1 3
+ &mux_SD1_DATA_2 3
+ &mux_SD1_DATA_3 3
+ >;
+ };
+ };
+ pinmux: pinmux {
+ compatible = "fh,fh-pinmux";
+ #list-cells = <1>;
+ mux_AC_I2S_CLK: AC_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_AC_I2S_DI: AC_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_AC_I2S_DO: AC_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_AC_I2S_WS: AC_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_AC_MCLK: AC_MCLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+
+ mux_ARC_JTAG_TCK: ARC_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_ARC_JTAG_TDI: ARC_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_ARC_JTAG_TDO: ARC_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_ARC_JTAG_TMS: ARC_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_ARC_JTAG_TRSTN: ARC_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_ARM_JTAG_TCK: ARM_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_ARM_JTAG_TDI: ARM_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_ARM_JTAG_TDO: ARM_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_ARM_JTAG_TMS: ARM_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_ARM_JTAG_TRSTN: ARM_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+
+ mux_DW_I2S_CLK: DW_I2S_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_DW_I2S_DI: DW_I2S_DI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_DW_I2S_DO: DW_I2S_DO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_DW_I2S_WS: DW_I2S_WS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+
+ mux_ETH_LINK_ACT: ETH_LINK_ACT {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad1
+ &pad63
+ >;
+ };
+ mux_ETH_LINK_SPD: ETH_LINK_SPD {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+ mux_ETH_LINK_STA: ETH_LINK_STA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad2
+ &pad64
+ >;
+ };
+
+ mux_I2C0_SCL: I2C0_SCL {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_I2C0_SDA: I2C0_SDA {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+
+ mux_I2C1_SCL: I2C1_SCL {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad11
+ &pad30
+ &pad46
+ >;
+ };
+ mux_I2C1_SDA: I2C1_SDA {
+ #list-cells = <1>;
+ select = <2>;
+ fh,pads = <
+ &pad12
+ &pad31
+ &pad47
+ >;
+ };
+
+ mux_I2C2_SCL: I2C2_SCL {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad16
+ &pad57
+ >;
+ };
+ mux_I2C2_SDA: I2C2_SDA {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad17
+ &pad58
+ >;
+ };
+
+ mux_MAC_MDC: MAC_MDC {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <0>;
+ fh,pads = <
+ &pad28
+ &pad63
+ >;
+ };
+ mux_MAC_MDIO: MAC_MDIO {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <0>;
+ fh,pads = <
+ &pad29
+ &pad64
+ >;
+ };
+ mux_MAC_REF_CLK: MAC_REF_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad21
+ >;
+ };
+ mux_MAC_RMII_CLK: MAC_RMII_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_MAC_RXDV: MAC_RXDV {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_MAC_RXD_0: MAC_RXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_MAC_RXD_1: MAC_RXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_MAC_TXD_0: MAC_TXD_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_MAC_TXD_1: MAC_TXD_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_MAC_TXEN: MAC_TXEN {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+
+ mux_PAE_JTAG_TCK: PAE_JTAG_TCK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_PAE_JTAG_TDI: PAE_JTAG_TDI {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_PAE_JTAG_TDO: PAE_JTAG_TDO {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_PAE_JTAG_TMS: PAE_JTAG_TMS {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_PAE_JTAG_TRSTN: PAE_JTAG_TRSTN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+
+ mux_PWM0: PWM0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_PWM1: PWM1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_PWM10: PWM10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_PWM11: PWM11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_PWM2: PWM2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ &pad18
+ &pad20
+ >;
+ };
+ mux_PWM3: PWM3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ &pad19
+ &pad22
+ >;
+ };
+ mux_PWM4: PWM4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad23
+ >;
+ };
+ mux_PWM5: PWM5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad24
+ >;
+ };
+ mux_PWM6: PWM6 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad25
+ &pad37
+ >;
+ };
+ mux_PWM7: PWM7 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad26
+ &pad38
+ >;
+ };
+ mux_PWM8: PWM8 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad27
+ &pad39
+ >;
+ };
+ mux_PWM9: PWM9 {
+ #list-cells = <1>;
+ select = <1>;
+ fh,pads = <
+ &pad28
+ &pad40
+ >;
+ };
+
+ mux_RTC_CLK: RTC_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+
+ mux_SADC_XAIN0: SADC_XAIN0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_SADC_XAIN1: SADC_XAIN1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_SADC_XAIN2: SADC_XAIN2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_SADC_XAIN3: SADC_XAIN3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+
+ mux_SD0_CD: SD0_CD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_SD0_CLK: SD0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <3>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_SD0_CMD_RSP: SD0_CMD_RSP {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_SD0_DATA_0: SD0_DATA_0 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_SD0_DATA_1: SD0_DATA_1 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_SD0_DATA_2: SD0_DATA_2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_SD0_DATA_3: SD0_DATA_3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <2>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+
+ mux_SD1_CD: SD1_CD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad10
+ &pad22
+ &pad31
+ &pad41
+ &pad63
+ >;
+ };
+ mux_SD1_CLK: SD1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <3>;
+ fh,pads = <
+ &pad9
+ &pad20
+ &pad30
+ &pad42
+ >;
+ };
+ mux_SD1_CMD_RSP: SD1_CMD_RSP {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad23
+ &pad32
+ &pad43
+ >;
+ };
+ mux_SD1_DATA_0: SD1_DATA_0 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad12
+ &pad24
+ &pad33
+ &pad44
+ >;
+ };
+ mux_SD1_DATA_1: SD1_DATA_1 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad25
+ &pad34
+ &pad45
+ >;
+ };
+ mux_SD1_DATA_2: SD1_DATA_2 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad26
+ &pad35
+ &pad46
+ >;
+ };
+ mux_SD1_DATA_3: SD1_DATA_3 {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad15
+ &pad27
+ &pad36
+ &pad47
+ >;
+ };
+
+ mux_SENSOR_CLK: SENSOR_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+
+ mux_SSI0_CLK: SSI0_CLK {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_SSI0_D2: SSI0_D2 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_SSI0_D3: SSI0_D3 {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_SSI0_RXD: SSI0_RXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_SSI0_TXD: SSI0_TXD {
+ #list-cells = <1>;
+ select = <0>;
+ ds = <4>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+
+ mux_SSI1_CLK: SSI1_CLK {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad11
+ &pad37
+ &pad48
+ &pad53
+ >;
+ };
+ mux_SSI1_RXD: SSI1_RXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad14
+ &pad40
+ &pad51
+ &pad55
+ >;
+ };
+ mux_SSI1_TXD: SSI1_TXD {
+ #list-cells = <1>;
+ select = <2>;
+ ds = <2>;
+ fh,pads = <
+ &pad13
+ &pad39
+ &pad50
+ &pad54
+ >;
+ };
+
+ mux_SSI2_CLK: SSI2_CLK {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad37
+ &pad48
+ >;
+ };
+ mux_SSI2_CSN_0: SSI2_CSN_0 {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad38
+ &pad49
+ >;
+ };
+ mux_SSI2_RXD: SSI2_RXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad40
+ &pad51
+ >;
+ };
+ mux_SSI2_TXD: SSI2_TXD {
+ #list-cells = <1>;
+ select = <1>;
+ ds = <2>;
+ fh,pads = <
+ &pad39
+ &pad50
+ >;
+ };
+
+ mux_UART0_RX: UART0_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_UART0_TX: UART0_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+
+ mux_UART1_RX: UART1_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ &pad33
+ &pad47
+ >;
+ };
+ mux_UART1_TX: UART1_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ &pad32
+ &pad46
+ >;
+ };
+
+ mux_UART2_RX: UART2_RX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ &pad17
+ &pad35
+ &pad58
+ >;
+ };
+ mux_UART2_TX: UART2_TX {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ &pad16
+ &pad34
+ &pad57
+ >;
+ };
+
+ mux_USB_PWREN: USB_PWREN {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ &pad41
+ >;
+ };
+
+ mux_GPIO0: GPIO0 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad37
+ >;
+ };
+ mux_GPIO1: GPIO1 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad38
+ >;
+ };
+ mux_GPIO2: GPIO2 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad39
+ >;
+ };
+ mux_GPIO3: GPIO3 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad40
+ >;
+ };
+ mux_GPIO4: GPIO4 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad41
+ >;
+ };
+ mux_GPIO5: GPIO5 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad42
+ >;
+ };
+ mux_GPIO6: GPIO6 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad43
+ >;
+ };
+ mux_GPIO7: GPIO7 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad44
+ >;
+ };
+ mux_GPIO8: GPIO8 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad45
+ >;
+ };
+ mux_GPIO9: GPIO9 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad46
+ >;
+ };
+ mux_GPIO10: GPIO10 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad47
+ >;
+ };
+ mux_GPIO11: GPIO11 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad48
+ >;
+ };
+ mux_GPIO12: GPIO12 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad7
+ >;
+ };
+ mux_GPIO13: GPIO13 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad8
+ >;
+ };
+ mux_GPIO14: GPIO14 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad49
+ >;
+ };
+ mux_GPIO15: GPIO15 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad50
+ >;
+ };
+ mux_GPIO16: GPIO16 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad51
+ >;
+ };
+ mux_GPIO17: GPIO17 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad52
+ >;
+ };
+ mux_GPIO18: GPIO18 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad53
+ >;
+ };
+ mux_GPIO19: GPIO19 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad54
+ >;
+ };
+ mux_GPIO20: GPIO20 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad55
+ >;
+ };
+ mux_GPIO21: GPIO21 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad56
+ >;
+ };
+ mux_GPIO22: GPIO22 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad57
+ >;
+ };
+ mux_GPIO23: GPIO23 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad58
+ >;
+ };
+ mux_GPIO24: GPIO24 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad61
+ >;
+ };
+ mux_GPIO25: GPIO25 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad62
+ >;
+ };
+ mux_GPIO26: GPIO26 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad59
+ >;
+ };
+ mux_GPIO27: GPIO27 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad60
+ >;
+ };
+ mux_GPIO28: GPIO28 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad63
+ >;
+ };
+ mux_GPIO29: GPIO29 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad64
+ >;
+ };
+ mux_GPIO30: GPIO30 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad0
+ >;
+ };
+ mux_GPIO31: GPIO31 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad1
+ >;
+ };
+ mux_GPIO32: GPIO32 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad2
+ >;
+ };
+ mux_GPIO33: GPIO33 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad3
+ >;
+ };
+ mux_GPIO34: GPIO34 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad4
+ >;
+ };
+ mux_GPIO35: GPIO35 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad5
+ >;
+ };
+ mux_GPIO36: GPIO36 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad6
+ >;
+ };
+ mux_GPIO37: GPIO37 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad11
+ >;
+ };
+ mux_GPIO38: GPIO38 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad12
+ >;
+ };
+ mux_GPIO39: GPIO39 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad9
+ >;
+ };
+ mux_GPIO40: GPIO40 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad10
+ >;
+ };
+ mux_GPIO41: GPIO41 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad13
+ >;
+ };
+ mux_GPIO42: GPIO42 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad14
+ >;
+ };
+ mux_GPIO43: GPIO43 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad16
+ >;
+ };
+ mux_GPIO44: GPIO44 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad17
+ >;
+ };
+ mux_GPIO45: GPIO45 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad18
+ >;
+ };
+ mux_GPIO46: GPIO46 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad19
+ >;
+ };
+ mux_GPIO47: GPIO47 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad15
+ >;
+ };
+ mux_GPIO48: GPIO48 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad20
+ >;
+ };
+ mux_GPIO49: GPIO49 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad22
+ >;
+ };
+ mux_GPIO50: GPIO50 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad23
+ >;
+ };
+ mux_GPIO51: GPIO51 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad24
+ >;
+ };
+ mux_GPIO52: GPIO52 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad25
+ >;
+ };
+ mux_GPIO53: GPIO53 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad26
+ >;
+ };
+ mux_GPIO54: GPIO54 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad27
+ >;
+ };
+ mux_GPIO55: GPIO55 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad28
+ >;
+ };
+ mux_GPIO56: GPIO56 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad29
+ >;
+ };
+ mux_GPIO57: GPIO57 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad30
+ >;
+ };
+ mux_GPIO58: GPIO58 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad31
+ >;
+ };
+ mux_GPIO59: GPIO59 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad32
+ >;
+ };
+ mux_GPIO60: GPIO60 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad33
+ >;
+ };
+ mux_GPIO61: GPIO61 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad34
+ >;
+ };
+ mux_GPIO62: GPIO62 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad35
+ >;
+ };
+ mux_GPIO63: GPIO63 {
+ #list-cells = <1>;
+ select = <0>;
+ fh,pads = <
+ &pad36
+ >;
+ };
+ };
+ pinpad: pinpad {
+ compatible = "fh,fh-pinpad";
+ pad0: PAD_BOOT_MODE_CFG {
+ index = <0>;
+ funcs = "GPIO30";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad1: PAD_BOOT_SEL1_CFG {
+ index = <1>;
+ funcs = "GPIO31", "ETH_LINK_ACT";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad2: PAD_BOOT_SEL0_CFG {
+ index = <2>;
+ funcs = "GPIO32", "ETH_LINK_STA", "ETH_LINK_SPD";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad3: PAD_UART0_TX_CFG {
+ index = <3>;
+ funcs = "UART0_TX", "GPIO33";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad4: PAD_UART0_RX_CFG {
+ index = <4>;
+ funcs = "UART0_RX", "GPIO34";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad5: PAD_I2C0_SCL_CFG {
+ index = <5>;
+ funcs = "I2C0_SCL", "GPIO35";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad6: PAD_I2C0_SDA_CFG {
+ index = <6>;
+ funcs = "I2C0_SDA", "GPIO36";
+ pupd = <1>;
+ ds = <0>;
+ };
+ pad7: PAD_SENSOR_CLK_CFG {
+ index = <7>;
+ funcs = "SENSOR_CLK", "GPIO12";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad8: PAD_SENSOR_RSTN_CFG {
+ index = <8>;
+ funcs = "GPIO13";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad9: PAD_UART1_TX_CFG {
+ index = <9>;
+ funcs = "UART1_TX", "GPIO39", "", "SD1_CLK", "", "",
+ "TEST_O_INT_RMII_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad10: PAD_UART1_RX_CFG {
+ index = <10>;
+ funcs = "UART1_RX", "GPIO40", "", "SD1_CD", "", "",
+ "TEST_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad11: PAD_I2C1_SCL_CFG {
+ index = <11>;
+ funcs = "I2C1_SCL", "GPIO37", "PWM2", "SD1_CMD_RSP", "",
+ "SSI1_CLK", "TEST_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad12: PAD_I2C1_SDA_CFG {
+ index = <12>;
+ funcs = "I2C1_SDA", "GPIO38", "PWM3", "SD1_DATA_0", "",
+ "SSI1_CSN_0", "TEST_INT_RMII_TXEN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad13: PAD_UART2_TX_CFG {
+ index = <13>;
+ funcs = "UART2_TX", "GPIO41", "PWM4", "SD1_DATA_1", "",
+ "SSI1_TXD", "TEST_O_INT_RMII_RXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad14: PAD_UART2_RX_CFG {
+ index = <14>;
+ funcs = "UART2_RX", "GPIO42", "PWM5", "SD1_DATA_2", "",
+ "SSI1_RXD", "TEST_O_INT_RMII_RXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad15: PAD_USB_PWREN_CFG {
+ index = <15>;
+ funcs = "USB_PWREN", "GPIO47", "", "SD1_DATA_3", "", "",
+ "TEST_O_INT_RMII_CRSDV";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad16: PAD_PWM0_CFG {
+ index = <16>;
+ funcs = "PWM0", "GPIO43", "I2C2_SCL", "UART2_TX", "", "",
+ "TEST_O_INT_RMII_TXD_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad17: PAD_PWM1_CFG {
+ index = <17>;
+ funcs = "PWM1", "GPIO44", "I2C2_SDA", "UART2_RX", "", "",
+ "TEST_O_INT_RMII_TXD_1";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad18: PAD_PWM2_CFG {
+ index = <18>;
+ funcs = "PWM2", "GPIO45";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad19: PAD_PWM3_CFG {
+ index = <19>;
+ funcs = "PWM3", "GPIO46";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad20: PAD_MAC_RMII_CLK_CFG {
+ index = <20>;
+ funcs = "MAC_RMII_CLK", "GPIO48", "SD1_CLK", "PWM2";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad21: PAD_MAC_REF_CLK_CFG {
+ index = <21>;
+ funcs = "MAC_REF_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad22: PAD_MAC_TXD0_CFG {
+ index = <22>;
+ funcs = "MAC_TXD_0", "GPIO49", "SD1_CD", "PWM3";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad23: PAD_MAC_TXD1_CFG {
+ index = <23>;
+ funcs = "MAC_TXD_1", "GPIO50", "SD1_CMD_RSP", "PWM4";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad24: PAD_MAC_TXEN_CFG {
+ index = <24>;
+ funcs = "MAC_TXEN", "GPIO51", "SD1_DATA_0", "PWM5";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad25: PAD_MAC_RXD0_CFG {
+ index = <25>;
+ funcs = "MAC_RXD_0", "GPIO52", "SD1_DATA_1", "PWM6";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad26: PAD_MAC_RXD1_CFG {
+ index = <26>;
+ funcs = "MAC_RXD_1", "GPIO53", "SD1_DATA_2", "PWM7";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad27: PAD_MAC_RXDV_CFG {
+ index = <27>;
+ funcs = "MAC_RXDV", "GPIO54", "SD1_DATA_3", "PWM8";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad28: PAD_MAC_MDC_CFG {
+ index = <28>;
+ funcs = "MAC_MDC", "GPIO55", "", "PWM9";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad29: PAD_MAC_MDIO_CFG {
+ index = <29>;
+ funcs = "MAC_MDIO", "GPIO56";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad30: PAD_SD1_CLK_CFG {
+ index = <30>;
+ funcs = "SD1_CLK", "GPIO57", "I2C1_SCL";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad31: PAD_SD1_CD_CFG {
+ index = <31>;
+ funcs = "SD1_CD", "GPIO58", "I2C1_SDA";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad32: PAD_SD1_CMD_RSP_CFG {
+ index = <32>;
+ funcs = "SD1_CMD_RSP", "GPIO59", "UART1_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad33: PAD_SD1_DATA_0_CFG {
+ index = <33>;
+ funcs = "SD1_DATA_0", "GPIO60", "UART1_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad34: PAD_SD1_DATA_1_CFG {
+ index = <34>;
+ funcs = "SD1_DATA_1", "GPIO61", "UART2_TX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad35: PAD_SD1_DATA_2_CFG {
+ index = <35>;
+ funcs = "SD1_DATA_2", "GPIO62", "UART2_RX";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad36: PAD_SD1_DATA_3_CFG {
+ index = <36>;
+ funcs = "SD1_DATA_3", "GPIO63";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad37: PAD_GPIO_0_CFG {
+ index = <37>;
+ funcs = "ARM_JTAG_TRSTN", "GPIO0", "AC_I2S_DO", "DW_I2S_DO",
+ "SSI1_CLK", "SSI2_CLK", "ACIP_ADDAT", "PWM6",
+ "TEST_O_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad38: PAD_GPIO_1_CFG {
+ index = <38>;
+ funcs = "ARM_JTAG_TDO", "GPIO1", "AC_I2S_DI", "DW_I2S_DI",
+ "SSI1_CSN_0", "SSI2_CSN_0", "ACIP_DADAT", "PWM7",
+ "TEST_O_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad39: PAD_GPIO_2_CFG {
+ index = <39>;
+ funcs = "ARM_JTAG_TDI", "GPIO2", "AC_I2S_CLK", "DW_I2S_CLK",
+ "SSI1_TXD", "SSI2_TXD", "ACIP_ADBCLK", "PWM8",
+ "TEST_O_INT_SMI_MDIO_O";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad40: PAD_GPIO_3_CFG {
+ index = <40>;
+ funcs = "ARM_JTAG_TCK", "GPIO3", "AC_I2S_WS", "DW_I2S_WS",
+ "SSI1_RXD", "SSI2_RXD", "ACIP_ADLRC", "PWM9",
+ "TEST_I_INT_SMI_MDIO_I";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad41: PAD_GPIO_4_CFG {
+ index = <41>;
+ funcs = "ARM_JTAG_TMS", "GPIO4", "AC_MCLK", "USB_PWREN",
+ "SD1_CD", "TEST_I_INT_SMI_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad42: PAD_SSI0_CLK_CFG {
+ index = <42>;
+ funcs = "SSI0_CLK", "GPIO5", "", "", "SD1_CLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad43: PAD_SSI0_CSN_0_CFG {
+ index = <43>;
+ funcs = "SSI0_CSN_0", "GPIO6", "", "", "SD1_CMD_RSP";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad44: PAD_SSI0_TXD_CFG {
+ index = <44>;
+ funcs = "SSI0_TXD", "GPIO7", "", "", "SD1_DATA_0";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad45: PAD_SSI0_RXD_CFG {
+ index = <45>;
+ funcs = "SSI0_RXD", "GPIO8", "", "", "SD1_DATA_1";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad46: PAD_SSI0_D2_CFG {
+ index = <46>;
+ funcs = "SSI0_D2", "GPIO9", "UART1_TX", "I2C1_SCL",
+ "SD1_DATA_2";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad47: PAD_SSI0_D3_CFG {
+ index = <47>;
+ funcs = "SSI0_D3", "GPIO10", "UART1_RX", "I2C1_SDA",
+ "SD1_DATA_3";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad48: PAD_SSI1_CLK_CFG {
+ index = <48>;
+ funcs = "SSI1_CLK", "GPIO11", "SSI2_CLK";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad49: PAD_SSI1_CSN_0_CFG {
+ index = <49>;
+ funcs = "SSI1_CSN_0", "GPIO14", "SSI2_CSN_0";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad50: PAD_SSI1_TXD_CFG {
+ index = <50>;
+ funcs = "SSI1_TXD", "GPIO15", "SSI2_TXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad51: PAD_SSI1_RXD_CFG {
+ index = <51>;
+ funcs = "SSI1_RXD", "GPIO16", "SSI2_RXD";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad52: PAD_SD0_CD_CFG {
+ index = <52>;
+ funcs = "SD0_CD", "GPIO17", "", "ARC_JTAG_TRSTN",
+ "PAE_JTAG_TRSTN";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad53: PAD_SD0_CLK_CFG {
+ index = <53>;
+ funcs = "SD0_CLK", "GPIO18", "SSI1_CLK", "ARC_JTAG_TDO",
+ "PAE_JTAG_TDO";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad54: PAD_SD0_CMD_RSP_CFG {
+ index = <54>;
+ funcs = "SD0_CMD_RSP", "GPIO19", "SSI1_TXD", "ARC_JTAG_TDI",
+ "PAE_JTAG_TDI";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad55: PAD_SD0_DATA_0_CFG {
+ index = <55>;
+ funcs = "SD0_DATA_0", "GPIO20", "SSI1_RXD", "ARC_JTAG_TCK",
+ "PAE_JTAG_TCK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad56: PAD_SD0_DATA_1_CFG {
+ index = <56>;
+ funcs = "SD0_DATA_1", "GPIO21", "SSI1_CSN_0", "ARC_JTAG_TMS",
+ "PAE_JTAG_TMS";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad57: PAD_SD0_DATA_2_CFG {
+ index = <57>;
+ funcs = "SD0_DATA_2", "GPIO22", "", "UART2_TX", "I2C2_SCL", "",
+ "ACIP_DABCLK";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad58: PAD_SD0_DATA_3_CFG {
+ index = <58>;
+ funcs = "SD0_DATA_3", "GPIO23", "SSI1_CSN_0", "UART2_RX",
+ "I2C2_SDA", "", "ACIP_DALRC";
+ pupd = <0>;
+ ds = <2>;
+ };
+ pad59: PAD_SADC_XAIN0_CFG {
+ index = <59>;
+ funcs = "SADC_XAIN0", "GPIO26";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad60: PAD_SADC_XAIN1_CFG {
+ index = <60>;
+ funcs = "SADC_XAIN1", "GPIO27";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad61: PAD_SADC_XAIN2_CFG {
+ index = <61>;
+ funcs = "SADC_XAIN2", "GPIO24";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad62: PAD_SADC_XAIN3_CFG {
+ index = <62>;
+ funcs = "SADC_XAIN3", "GPIO25";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad63: PAD_GPIO_28_CFG {
+ index = <63>;
+ funcs = "GPIO28", "", "ETH_LINK_ACT", "PWM10",
+ "USB_DBG_CLK", "SD1_CD", "TEST_O_INT_RMII_TXEN",
+ "MAC_MDC";
+ pupd = <0>;
+ ds = <0>;
+ };
+ pad64: PAD_GPIO_29_CFG {
+ index = <64>;
+ funcs = "GPIO29", "", "ETH_LINK_STA", "PWM11", "RTC_CLK",
+ "ETH_LINK_SPD", "TEST_O_INT_SMI_MDIO_OE",
+ "MAC_MDIO";
+ pupd = <0>;
+ ds = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/configs/fh8852v200_defconfig b/arch/arm/configs/fh8852v200_defconfig
new file mode 100644
index 00000000..b8c52f46
--- /dev/null
+++ b/arch/arm/configs/fh8852v200_defconfig
@@ -0,0 +1,2253 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8852 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8852v200"
+# CONFIG_MACH_FH8856V200 is not set
+CONFIG_MACH_FH8852V200=y
+# CONFIG_MACH_FH8858V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_MTD_UBI is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_PINCTRL_MISC_DEV=y
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+# CONFIG_SPI_FH_SLAVE is not set
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+CONFIG_USB_DWC2_DMA=y
+# CONFIG_USB_DWC2_DMA_DESC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+# CONFIG_DW_DMAC is not set
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=14
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_FH_CESA is not set
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8852v200_of_defconfig b/arch/arm/configs/fh8852v200_of_defconfig
new file mode 100644
index 00000000..a74ea3c9
--- /dev/null
+++ b/arch/arm/configs/fh8852v200_of_defconfig
@@ -0,0 +1,2332 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8852v200"
+CONFIG_MACH_FH8852V200=y
+# CONFIG_MACH_FH8856V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+
+#
+# fh inside or outside phy sel
+#
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCTRL_FULLHAN=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+CONFIG_POWER_RESET_FH=y
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_GPIO_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SNVS is not set
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+# CONFIG_DW_DMAC is not set
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_FSL_EDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=2
+# CONFIG_PWM_FSL_FTM is not set
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8852v210_defconfig b/arch/arm/configs/fh8852v210_defconfig
new file mode 100644
index 00000000..9e8583c1
--- /dev/null
+++ b/arch/arm/configs/fh8852v210_defconfig
@@ -0,0 +1,2253 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8852 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8852v210"
+# CONFIG_MACH_FH8856V200 is not set
+CONFIG_MACH_FH8852V210=y
+# CONFIG_MACH_FH8858V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_MTD_UBI is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_PINCTRL_MISC_DEV=y
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+# CONFIG_SPI_FH_SLAVE is not set
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+CONFIG_USB_DWC2_DMA=y
+# CONFIG_USB_DWC2_DMA_DESC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+# CONFIG_DW_DMAC is not set
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=14
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_FH_CESA is not set
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8852v210_of_defconfig b/arch/arm/configs/fh8852v210_of_defconfig
new file mode 100644
index 00000000..f6a7346f
--- /dev/null
+++ b/arch/arm/configs/fh8852v210_of_defconfig
@@ -0,0 +1,2332 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8852v210"
+CONFIG_MACH_FH8852V210=y
+# CONFIG_MACH_FH8856V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+
+#
+# fh inside or outside phy sel
+#
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCTRL_FULLHAN=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+CONFIG_POWER_RESET_FH=y
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_GPIO_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SNVS is not set
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+# CONFIG_DW_DMAC is not set
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_FSL_EDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=2
+# CONFIG_PWM_FSL_FTM is not set
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8856v200_defconfig b/arch/arm/configs/fh8856v200_defconfig
new file mode 100644
index 00000000..e9c4bb47
--- /dev/null
+++ b/arch/arm/configs/fh8856v200_defconfig
@@ -0,0 +1,2253 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8852 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8856v200"
+CONFIG_MACH_FH8856V200=y
+# CONFIG_MACH_FH8852V200 is not set
+# CONFIG_MACH_FH8858V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_MTD_UBI is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_PINCTRL_MISC_DEV=y
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+# CONFIG_SPI_FH_SLAVE is not set
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+CONFIG_USB_DWC2_DMA=y
+# CONFIG_USB_DWC2_DMA_DESC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+# CONFIG_DW_DMAC is not set
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=14
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_FH_CESA is not set
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8856v200_of_defconfig b/arch/arm/configs/fh8856v200_of_defconfig
new file mode 100644
index 00000000..4a959402
--- /dev/null
+++ b/arch/arm/configs/fh8856v200_of_defconfig
@@ -0,0 +1,2332 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8856v200"
+CONFIG_MACH_FH8856V200=y
+# CONFIG_MACH_FH8852V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+
+#
+# fh inside or outside phy sel
+#
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCTRL_FULLHAN=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+CONFIG_POWER_RESET_FH=y
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_GPIO_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SNVS is not set
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+# CONFIG_DW_DMAC is not set
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_FSL_EDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=2
+# CONFIG_PWM_FSL_FTM is not set
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8856v210_defconfig b/arch/arm/configs/fh8856v210_defconfig
new file mode 100644
index 00000000..34856420
--- /dev/null
+++ b/arch/arm/configs/fh8856v210_defconfig
@@ -0,0 +1,2253 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8852 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8856v210"
+CONFIG_MACH_FH8856V210=y
+# CONFIG_MACH_FH8852V200 is not set
+# CONFIG_MACH_FH8858V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_MTD_UBI is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_PINCTRL_MISC_DEV=y
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+# CONFIG_SPI_FH_SLAVE is not set
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+CONFIG_USB_DWC2_DMA=y
+# CONFIG_USB_DWC2_DMA_DESC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+# CONFIG_DW_DMAC is not set
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=14
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_FH_CESA is not set
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8856v210_of_defconfig b/arch/arm/configs/fh8856v210_of_defconfig
new file mode 100644
index 00000000..e80393de
--- /dev/null
+++ b/arch/arm/configs/fh8856v210_of_defconfig
@@ -0,0 +1,2332 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8856v210"
+CONFIG_MACH_FH8856V210=y
+# CONFIG_MACH_FH8852V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+
+#
+# fh inside or outside phy sel
+#
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCTRL_FULLHAN=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+CONFIG_POWER_RESET_FH=y
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_GPIO_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SNVS is not set
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+# CONFIG_DW_DMAC is not set
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_FSL_EDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=2
+# CONFIG_PWM_FSL_FTM is not set
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8858v200_defconfig b/arch/arm/configs/fh8858v200_defconfig
new file mode 100644
index 00000000..00399a14
--- /dev/null
+++ b/arch/arm/configs/fh8858v200_defconfig
@@ -0,0 +1,2253 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8852 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8858v200"
+# CONFIG_MACH_FH8856V200 is not set
+# CONFIG_MACH_FH8852V200 is not set
+CONFIG_MACH_FH8858V200=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_MTD_UBI is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_PINCTRL_MISC_DEV=y
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+# CONFIG_SPI_FH_SLAVE is not set
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+CONFIG_USB_DWC2_DMA=y
+# CONFIG_USB_DWC2_DMA_DESC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+# CONFIG_DW_DMAC is not set
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=14
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_FH_CESA is not set
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8858v200_of_defconfig b/arch/arm/configs/fh8858v200_of_defconfig
new file mode 100644
index 00000000..0905961c
--- /dev/null
+++ b/arch/arm/configs/fh8858v200_of_defconfig
@@ -0,0 +1,2332 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8858v200"
+CONFIG_MACH_FH8858V200=y
+# CONFIG_MACH_FH8852V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+
+#
+# fh inside or outside phy sel
+#
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCTRL_FULLHAN=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+CONFIG_POWER_RESET_FH=y
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_GPIO_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SNVS is not set
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+# CONFIG_DW_DMAC is not set
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_FSL_EDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=2
+# CONFIG_PWM_FSL_FTM is not set
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8858v210_defconfig b/arch/arm/configs/fh8858v210_defconfig
new file mode 100644
index 00000000..a84c57f6
--- /dev/null
+++ b/arch/arm/configs/fh8858v210_defconfig
@@ -0,0 +1,2253 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8852 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8858v210"
+# CONFIG_MACH_FH8856V200 is not set
+# CONFIG_MACH_FH8852V200 is not set
+CONFIG_MACH_FH8858V210=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_MTD_UBI is not set
+# CONFIG_OF is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_PINCTRL_MISC_DEV=y
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+# CONFIG_SPI_FH_SLAVE is not set
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+CONFIG_USB_DWC2_DMA=y
+# CONFIG_USB_DWC2_DMA_DESC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+# CONFIG_DW_DMAC is not set
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=14
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_FH_CESA is not set
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/configs/fh8858v210_of_defconfig b/arch/arm/configs/fh8858v210_of_defconfig
new file mode 100644
index 00000000..b7ea132a
--- /dev/null
+++ b/arch/arm/configs/fh8858v210_of_defconfig
@@ -0,0 +1,2332 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.129 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_TINY_KERNEL=y
+CONFIG_NTP=y
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+# CONFIG_KERNEL_NO_COMPRESS is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DL is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="usr/rootfs.cpio.xz"
+CONFIG_INITRAMFS_ROOT_UID=0
+CONFIG_INITRAMFS_ROOT_GID=0
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_RD_XZ=y
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STATIC_KEYS_SELFTEST is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_MULTIPLATFORM is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_FULLHAN=y
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Fullhan platform type
+#
+# CONFIG_FH_FASTBOOT is not set
+# CONFIG_ARCH_FH8833 is not set
+# CONFIG_ARCH_FH8856 is not set
+# CONFIG_ARCH_FH8626V100 is not set
+CONFIG_ARCH_FH885xV200=y
+# CONFIG_ARCH_FH865x is not set
+
+CONFIG_FH_CHIP_NAME="fh8858v210"
+CONFIG_MACH_FH8858V210=y
+# CONFIG_MACH_FH8852V200 is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+CONFIG_PJ4B_ERRATA_4742=y
+# CONFIG_ARM_ERRATA_326103 is not set
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_364296 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_CPU_SW_DOMAIN_PAN=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND=y
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+# CONFIG_SUSPEND is not set
+# CONFIG_PM is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARM_CPU_SUSPEND is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+CONFIG_IPV6_SIT=y
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_FOU is not set
+# CONFIG_IPV6_FOU_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+# CONFIG_CFG80211_DEFAULT_PS is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+# CONFIG_MAC80211 is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_GPIO is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+CONFIG_DST_CACHE=y
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+# CONFIG_BLK_DEV is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_FH_DW_I2S is not set
+# CONFIG_FH_ACW is not set
+CONFIG_FH_SADC_V3=y
+CONFIG_FH_EFUSE=y
+# CONFIG_FH_L2MEM is not set
+CONFIG_FH_CLK_MISC=y
+CONFIG_FH_PERF_MON=y
+# CONFIG_FH_TSENSOR is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_NET_VENDOR_FULLHAN=y
+CONFIG_FH_GMAC=y
+CONFIG_FH_GMAC_DA=y
+
+#
+# fh inside or outside phy sel
+#
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_USB_NET_DRIVERS=y
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_LAN78XX is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_ADMTEK=y
+CONFIG_WLAN_VENDOR_ATH=y
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH6KL is not set
+CONFIG_WLAN_VENDOR_ATMEL=y
+CONFIG_WLAN_VENDOR_BROADCOM=y
+# CONFIG_BRCMFMAC is not set
+CONFIG_WLAN_VENDOR_CISCO=y
+CONFIG_WLAN_VENDOR_INTEL=y
+CONFIG_WLAN_VENDOR_INTERSIL=y
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_WLAN_VENDOR_MARVELL=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_MWIFIEX is not set
+CONFIG_WLAN_VENDOR_MEDIATEK=y
+CONFIG_WLAN_VENDOR_RALINK=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+CONFIG_WLAN_VENDOR_RSI=y
+CONFIG_WLAN_VENDOR_ST=y
+CONFIG_WLAN_VENDOR_TI=y
+CONFIG_WLAN_VENDOR_ZYDAS=y
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+CONFIG_SERIAL_FULLHAN=y
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_FH_INTERRUPT=y
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+CONFIG_SPI_FH=y
+
+#
+# spi multi wire support
+#
+CONFIG_SPI_USE_MULTI_WIRE=y
+CONFIG_SPI_SWAP_MAX_DATA_WIDTH=16
+# CONFIG_SPI_USE_DMA is not set
+CONFIG_SPI_TINY_MEM=y
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCTRL_FULLHAN=y
+# CONFIG_PINCTRL_AMD is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+CONFIG_GPIO_FH=y
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+CONFIG_POWER_RESET_FH=y
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_CORE is not set
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CONFIG_WATCHDOG_SYSFS is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_GPIO_WATCHDOG is not set
+# CONFIG_XILINX_WATCHDOG is not set
+# CONFIG_ZIIRAVE_WATCHDOG is not set
+# CONFIG_CADENCE_WATCHDOG is not set
+# CONFIG_DW_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_FH_WATCHDOG=y
+# CONFIG_MEN_A21_WDT is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Watchdog Pretimeout Governors
+#
+# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# USB HID support
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+CONFIG_USB_WUSB_CBAF=y
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_HOST=y
+
+#
+# Gadget/Dual-role mode requires USB Gadget support to be enabled
+#
+# CONFIG_USB_DWC2_VBVALIDOVEN is not set
+# CONFIG_USB_DWC2_DEBUG is not set
+# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set
+# CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_FH=y
+CONFIG_MMC_FH_IDMAC=y
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+# CONFIG_RTC_I2C_AND_SPI is not set
+
+#
+# SPI and I2C RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SNVS is not set
+CONFIG_RTC_DRV_FH=y
+CONFIG_USE_TSENSOR=y
+# CONFIG_USE_TSENSOR_OFFSET is not set
+
+#
+# HID Sensor RTC drivers
+#
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+# CONFIG_DW_DMAC is not set
+# CONFIG_FH_DMAC is not set
+CONFIG_FH_AXI_DMAC=y
+CONFIG_FH_DMAC_MISC=y
+
+#
+# dma tinyconfig
+#
+CONFIG_CHANNEL_ALLOC_MEM_CLASSICS=y
+CONFIG_CHANNEL_ALLOC_DESC_NUM=32
+# CONFIG_FSL_EDMA is not set
+# CONFIG_INTEL_IDMA64 is not set
+# CONFIG_NBPFAXI_DMA is not set
+# CONFIG_QCOM_HIDMA_MGMT is not set
+# CONFIG_QCOM_HIDMA is not set
+
+#
+# DMA Clients
+#
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_FULLHAN_TIMER=y
+# CONFIG_FH_SIMPLE_TIMER is not set
+# CONFIG_ARM_TIMER_SP804 is not set
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+# CONFIG_PWM_SYSFS is not set
+# CONFIG_DEBUG_PWM_FS is not set
+CONFIG_PWM_FULLHAN=y
+CONFIG_FH_PWM_NUM=2
+# CONFIG_PWM_FSL_FTM is not set
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC_MAX_NR=1
+CONFIG_FULLHAN_INTC=y
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_FH_USB2_PHY is not set
+# CONFIG_PHY_SAMSUNG_USB2 is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V2 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_SWAP is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_OPTIMIZE_INLINING=y
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_INFO is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_STACKTRACE is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_HWLAT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+CONFIG_TRACING_EVENTS_GPIO=y
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=y
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+CONFIG_CRYPTO_USER_API=y
+# CONFIG_CRYPTO_USER_API_HASH is not set
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_FH_AES=y
+# CONFIG_CRYPTO_FH_AES_SUPPORT_DIRECT_MEM is not set
+# CONFIG_FH_AES_SELF_TEST is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/arch/arm/include/asm/mach/flash.h b/arch/arm/include/asm/mach/flash.h
index 4ca69fe2..0eea1ab7 100644
--- a/arch/arm/include/asm/mach/flash.h
+++ b/arch/arm/include/asm/mach/flash.h
@@ -26,7 +26,7 @@ struct mtd_info;
*/
struct flash_platform_data {
const char *map_name;
- const char *name;
+ char name[16];
unsigned int width;
int (*init)(void);
void (*exit)(void);
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 76cbd9c6..eaf74e04 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -98,7 +98,7 @@
#endif
#ifndef END_MEM
-#define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
+#define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
#endif
/*
@@ -143,8 +143,8 @@
*/
#define PHYS_RELATIVE(v_data, v_text) \
(((v_data) - PAGE_OFFSET + PLAT_PHYS_OFFSET) - \
- ((v_text) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + \
- CONFIG_XIP_PHYS_ADDR))
+ ((v_text) - XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) + \
+ CONFIG_XIP_PHYS_ADDR))
#else
#define PHYS_RELATIVE(v_data, v_text) ((v_data) - (v_text))
#endif
@@ -171,13 +171,13 @@
extern unsigned long __pv_phys_pfn_offset;
extern u64 __pv_offset;
-extern void fixup_pv_table(const void *, unsigned long);
+extern void fixup_pv_table(const void *addr, unsigned long size);
extern const void *__pv_table_begin, *__pv_table_end;
#define PHYS_OFFSET ((phys_addr_t)__pv_phys_pfn_offset << PAGE_SHIFT)
#define PHYS_PFN_OFFSET (__pv_phys_pfn_offset)
-#define __pv_stub(from,to,instr,type) \
+#define __pv_stub(from, to, instr, type) \
__asm__("@ __pv_stub\n" \
"1: " instr " %0, %1, %2\n" \
" .pushsection .pv_table,\"a\"\n" \
diff --git a/arch/arm/include/asm/string.h b/arch/arm/include/asm/string.h
index cf4f3aad..649b9866 100644
--- a/arch/arm/include/asm/string.h
+++ b/arch/arm/include/asm/string.h
@@ -26,14 +26,14 @@ extern void * memset(void *, int, __kernel_size_t);
extern void __memzero(void *ptr, __kernel_size_t n);
-#define memset(p,v,n) \
+#define memset(p, v, n) \
({ \
void *__p = (p); size_t __n = n; \
if ((__n) != 0) { \
if (__builtin_constant_p((v)) && (v) == 0) \
- __memzero((__p),(__n)); \
+ __memzero((__p), (__n)); \
else \
- memset((__p),(v),(__n)); \
+ memset((__p), (v), (__n)); \
} \
(__p); \
})
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 776757d1..9cc9e000 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -16,7 +16,9 @@
#include <asm/fpstate.h>
#include <asm/page.h>
+
#define THREAD_SIZE_ORDER 1
+
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define THREAD_START_SP (THREAD_SIZE - 8)
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index b7e0125c..4d8205db 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -182,11 +182,11 @@ extern int __get_user_64t_4(void *);
#define __get_user_check(x, p) \
({ \
unsigned long __limit = current_thread_info()->addr_limit - 1; \
+ unsigned int __ua_flags = uaccess_save_and_enable(); \
register const typeof(*(p)) __user *__p asm("r0") = (p);\
register typeof(x) __r2 asm("r2"); \
register unsigned long __l asm("r1") = __limit; \
register int __e asm("r0"); \
- unsigned int __ua_flags = uaccess_save_and_enable(); \
switch (sizeof(*(__p))) { \
case 1: \
if (sizeof((x)) >= 8) \
@@ -214,8 +214,8 @@ extern int __get_user_64t_4(void *);
break; \
default: __e = __get_user_bad(); break; \
} \
- uaccess_restore(__ua_flags); \
x = (typeof(*(p))) __r2; \
+ uaccess_restore(__ua_flags); \
__e; \
})
diff --git a/arch/arm/include/debug/fh.S b/arch/arm/include/debug/fh.S
new file mode 100644
index 00000000..020cd44b
--- /dev/null
+++ b/arch/arm/include/debug/fh.S
@@ -0,0 +1,44 @@
+/* linux/arch/arm/mach-fh/include/mach/debug-macro.S
+ *
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+/* note, for the boot process to work we have to keep the UART
+ * virtual address aligned to an 1MiB boundary for the L1
+ * mapping the head code makes. We keep the UART virtual address
+ * aligned and add in the offset when we load the value here.
+ */
+#include <mach/io.h>
+#include <chip.h>
+ .macro addruart, rp, rv, tmp
+ ldr \rp, =CONSOLE_REG_BASE
+ ldr \rv, =VA_CONSOLE_REG_BASE
+ .endm
+
+ .macro senduart,data,addr
+ strb \data, [\addr, #(0x00)] @ Write to Transmitter Holding Register
+ .endm
+
+ .macro waituart,data,addr
+1001:
+ ldr \data, [\addr, #(0x14)] @ Read Status Register
+ tst \data, #(0x40) @when TX FIFO Full, then wait
+ beq 1001b
+ .endm
+
+ .macro busyuart,data,addr
+@ stmfd r13!, {r4}
+1002:
+ ldr \data, [\addr, #(0x14)]
+ tst \data, #(0x40)
+ beq 1002b
+ .endm
+
+
+
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 04286fd9..f9579d83 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -447,6 +447,12 @@ __secondary_data:
* r13 = *virtual* address to jump to upon completion
*/
__enable_mmu:
+#if defined (CONFIG_CPU_V7)
+ /* remember in arm cortex-a7 all mmu facility is based on SMP bit */
+ mrc p15, 0, r5, c1, c0, 1
+ orr r5, #(1 << 6)
+ mcr p15, 0, r5, c1, c0, 1
+#endif
#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
orr r0, r0, #CR_A
#else
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 4f14b5ce..3a87e2f1 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -72,7 +72,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
#endif
offset = ELF32_R_SYM(rel->r_info);
- if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
+ if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))
+ ) {
pr_err("%s: section %u reloc %u: bad relocation sym offset\n",
module->name, relindex, i);
return -ENOEXEC;
@@ -81,7 +82,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
symname = strtab + sym->st_name;
- if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) {
+ if (rel->r_offset < 0 || rel->r_offset >
+ dstsec->sh_size - sizeof(u32)) {
pr_err("%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n",
module->name, relindex, i, symname,
rel->r_offset, dstsec->sh_size);
@@ -145,14 +147,14 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
*(u32 *)loc |= __opcode_to_mem_arm(offset);
break;
- case R_ARM_V4BX:
+ case R_ARM_V4BX:
/* Preserve Rm and the condition code. Alter
* other bits to re-code instruction as
* MOV PC,Rm.
*/
- *(u32 *)loc &= __opcode_to_mem_arm(0xf000000f);
- *(u32 *)loc |= __opcode_to_mem_arm(0x01a0f000);
- break;
+ *(u32 *)loc &= __opcode_to_mem_arm(0xf000000f);
+ *(u32 *)loc |= __opcode_to_mem_arm(0x01a0f000);
+ break;
case R_ARM_PREL31:
offset = *(u32 *)loc + sym->st_value - loc;
@@ -364,9 +366,9 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
if (maps[i].unw_sec && maps[i].txt_sec)
mod->arch.unwind[i] =
unwind_table_add(maps[i].unw_sec->sh_addr,
- maps[i].unw_sec->sh_size,
- maps[i].txt_sec->sh_addr,
- maps[i].txt_sec->sh_size);
+ maps[i].unw_sec->sh_size,
+ maps[i].txt_sec->sh_addr,
+ maps[i].txt_sec->sh_size);
#endif
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
s = find_mod_section(hdr, sechdrs, ".pv_table");
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 7dd14e83..46377c40 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -251,7 +251,7 @@ void __cpu_die(unsigned int cpu)
pr_err("CPU%u: cpu didn't die\n", cpu);
return;
}
- pr_notice("CPU%u: shutdown\n", cpu);
+ pr_debug("CPU%u: shutdown\n", cpu);
/*
* platform_cpu_kill() is generally expected to do the powering off
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0..9fe15799 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -17,22 +17,22 @@
#define PROC_INFO \
. = ALIGN(4); \
VMLINUX_SYMBOL(__proc_info_begin) = .; \
- *(.proc.info.init) \
+ KEEP(*(.proc.info.init)) \
VMLINUX_SYMBOL(__proc_info_end) = .;
#define HYPERVISOR_TEXT \
VMLINUX_SYMBOL(__hyp_text_start) = .; \
- *(.hyp.text) \
+ KEEP(*(.hyp.text)) \
VMLINUX_SYMBOL(__hyp_text_end) = .;
#define IDMAP_TEXT \
ALIGN_FUNCTION(); \
VMLINUX_SYMBOL(__idmap_text_start) = .; \
- *(.idmap.text) \
+ KEEP(*(.idmap.text)) \
VMLINUX_SYMBOL(__idmap_text_end) = .; \
. = ALIGN(PAGE_SIZE); \
VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \
- *(.hyp.idmap.text) \
+ KEEP(*(.hyp.idmap.text)) \
VMLINUX_SYMBOL(__hyp_idmap_text_end) = .;
#ifdef CONFIG_HOTPLUG_CPU
@@ -134,7 +134,7 @@ SECTIONS
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) {
__start___ex_table = .;
#ifdef CONFIG_MMU
- *(__ex_table)
+ KEEP(*(__ex_table))
#endif
__stop___ex_table = .;
}
@@ -171,14 +171,14 @@ SECTIONS
*/
__vectors_start = .;
.vectors 0xffff0000 : AT(__vectors_start) {
- *(.vectors)
+ KEEP(*(.vectors))
}
. = __vectors_start + SIZEOF(.vectors);
__vectors_end = .;
__stubs_start = .;
.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {
- *(.stubs)
+ KEEP(*(.stubs))
}
. = __stubs_start + SIZEOF(.stubs);
__stubs_end = .;
@@ -194,24 +194,24 @@ SECTIONS
}
.init.arch.info : {
__arch_info_begin = .;
- *(.arch.info.init)
+ KEEP(*(.arch.info.init))
__arch_info_end = .;
}
.init.tagtable : {
__tagtable_begin = .;
- *(.taglist.init)
+ KEEP(*(.taglist.init))
__tagtable_end = .;
}
#ifdef CONFIG_SMP_ON_UP
.init.smpalt : {
__smpalt_begin = .;
- *(.alt.smp.init)
+ KEEP(*(.alt.smp.init))
__smpalt_end = .;
}
#endif
.init.pv_table : {
__pv_table_begin = .;
- *(.pv_table)
+ KEEP(*(.pv_table))
__pv_table_end = .;
}
.init.data : {
diff --git a/arch/arm/mach-fh/Kconfig b/arch/arm/mach-fh/Kconfig
new file mode 100644
index 00000000..3518d065
--- /dev/null
+++ b/arch/arm/mach-fh/Kconfig
@@ -0,0 +1,142 @@
+
+if ARCH_FULLHAN
+
+menu "Fullhan platform type"
+
+
+menuconfig FH_FASTBOOT
+ bool "Fastboot configurations"
+ default n
+ help
+ Fullhan Fastboot configurations
+
+if FH_FASTBOOT
+config DEFERRED_INIICALLS
+ bool "Enable deferred initcalls support"
+ default n
+ help
+ enable deferred initcalls, use deferred_initcall() to deferred some initcalls,
+ after kernel boot, use cat /proc/deferred_initcalls to run all deferred initcalls
+
+if DEFERRED_INIICALLS
+config DEFERRED_INIICALLS_DEBUG
+ bool "Debug deferred initcalls"
+ default n
+
+config DEFERRED_INIICALLS_SLAB_SYSFS
+ bool "defer slab_sysfs_init"
+ default n
+ depends on SYSFS
+
+config DEFERRED_INIICALLS_IRQ_SYSFS
+ bool "defer irq_sysfs_init"
+ default n
+ depends on SYSFS
+
+config DEFERRED_INIICALLS_PARAM_SYSFS
+ bool "defer param_sysfs_init"
+ depends on SYSFS
+ default n
+
+config DEFERRED_INIICALLS_GMAC
+ bool "defer gmac driver init"
+ default n
+ depends on FH_GMAC=y
+
+config DEFERRED_INIICALLS_SPI
+ bool "defer spi driver init"
+ default n
+ depends on SPI_FH=y
+
+config DEFERRED_INIICALLS_MMC
+ bool "defer mmc driver init"
+ default n
+ depends on MMC_FH=y
+
+config DEFERRED_INIICALLS_USB
+ bool "defer usb driver init"
+ default n
+ depends on USB_DWC2=y
+
+config DEFERRED_INIICALLS_RTC
+ bool "defer rtc driver init"
+ default n
+ depends on RTC_DRV_FH=y
+endif
+
+endif
+
+choice
+prompt "Board"
+config ARCH_FH885xV200
+ bool "Fullhan FH885xV200"
+ select CPU_V6
+ select FULLHAN_INTC
+ select FULLHAN_TIMER
+ select PINCTRL if USE_OF
+ help
+ Support for Fullhan FH885xV200 SoC
+
+endchoice
+config FH_CHIP_NAME
+ string
+ prompt "Select chip name, keep default"
+ default "fh8856v200" if MACH_FH8856V200
+ default "fh8852v200" if MACH_FH8852V200
+ default "fh8858v200" if MACH_FH8858V200
+ default "fh8856v210" if MACH_FH8856V210
+ default "fh8852v210" if MACH_FH8852V210
+ default "fh8858v210" if MACH_FH8858V210
+
+config MACH_FH8856V200
+ bool "FullHan FH8856V200 board"
+ default n
+ depends on ARCH_FH885xV200
+ help
+ Configure this option to specify the whether the board used
+ for development is FH8856V200
+
+config MACH_FH8852V200
+ bool "FullHan FH8852V200 board"
+ default n
+ depends on ARCH_FH885xV200
+ help
+ Configure this option to specify the whether the board used
+ for development is FH8852V200
+
+config MACH_FH8858V200
+ bool "FullHan FH8858V200 board"
+ default n
+ depends on ARCH_FH885xV200
+ help
+ Configure this option to specify the whether the board used
+ for development is FH8858V200
+
+config MACH_FH8856V210
+ bool "FullHan FH8856V210 board"
+ default n
+ depends on ARCH_FH885xV200
+ help
+ Configure this option to specify the whether the board used
+ for development is FH8856V210
+
+config MACH_FH8852V210
+ bool "FullHan FH8852V210 board"
+ default n
+ depends on ARCH_FH885xV210
+ help
+ Configure this option to specify the whether the board used
+ for development is FH8852V200
+
+config MACH_FH8858V210
+ bool "FullHan FH8858V210 board"
+ default n
+ depends on ARCH_FH885xV200
+ help
+ Configure this option to specify the whether the board used
+ for development is FH8858V210
+
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-fh/Makefile b/arch/arm/mach-fh/Makefile
new file mode 100644
index 00000000..7f250d0c
--- /dev/null
+++ b/arch/arm/mach-fh/Makefile
@@ -0,0 +1,12 @@
+CONFIG_FH_CHIP_NAME := $(subst ",,$(CONFIG_FH_CHIP_NAME))
+EXTRA_CFLAGS += -Iarch/arm/mach-fh/$(CONFIG_FH_CHIP_NAME)
+
+obj-y += pmu.o fullhan.o fh_common.o fh_chipid.o
+
+ifneq ($(CONFIG_USE_OF),y)
+obj-y += pinctrl.o clock.o
+obj-y += $(CONFIG_FH_CHIP_NAME)/
+endif
+
+obj-$(CONFIG_SMP) += platsmp.o hotplug.o
+obj-$(CONFIG_ARM_FULLHAN_CPUIDLE) += cpuidle.o
diff --git a/arch/arm/mach-fh/Makefile.boot b/arch/arm/mach-fh/Makefile.boot
new file mode 100644
index 00000000..9703b95e
--- /dev/null
+++ b/arch/arm/mach-fh/Makefile.boot
@@ -0,0 +1,3 @@
+zreladdr-y := 0xA0008000
+params_phys-y := 0xA0000100
+initrd_phys-y := 0xA0800000
\ No newline at end of file
diff --git a/arch/arm/mach-fh/clock.c b/arch/arm/mach-fh/clock.c
new file mode 100644
index 00000000..b41616b0
--- /dev/null
+++ b/arch/arm/mach-fh/clock.c
@@ -0,0 +1,741 @@
+/*
+ * Clock and PLL control for FH devices
+ *
+ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <mach/io.h>
+#include <asm/bitops.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <mach/pmu.h>
+#include <mach/clock.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include "soc.h"
+
+
+#define PROC_FILE "driver/clock"
+
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clocks_lock);
+
+struct proc_dir_entry *proc_file;
+
+struct fh_clk_divider {
+ struct clk_hw hw;
+ u32 reg;
+ u32 prediv;
+ u32 div_flag;
+ u32 div_reg_mask;
+ spinlock_t *lock;
+};
+struct fh_clk_pllpr {
+ struct clk_hw hw;
+ u32 reg_ctrl0;
+ u32 reg_ctrl1;
+ u32 covpr_mask;
+ u32 flag;
+ spinlock_t *lock;
+};
+
+struct fh_clk_phase {
+ struct clk_hw hw;
+ u32 reg;
+ u32 mux;
+ spinlock_t *lock;
+};
+
+/*#define FH_CLK_DEBUG*/
+#define DIVVCO_ONE_DEVISION 0x0
+#define DIVVCO_TWO_DEVISION 0x8
+#define DIVVCO_FOUR_DEVISION 0xc
+#define DIVVCO_EIGHT_DEVISION 0xd
+#define DIVVCO_SIXTEEN_DEVISION 0xe
+#define DIVVCO_THIRTYTWO_DEVISION 0xf
+
+static unsigned long fh_clk_get_pll_pr_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned int reg, m, n, p, r = 1;
+ unsigned int clk_vco, divvcop = 1, shift;
+ u32 rate;
+ struct fh_clk_pllpr *pllpr = (struct fh_clk_pllpr *)hw;
+
+ reg = fh_pmu_get_reg(pllpr->reg_ctrl0);
+
+ m = reg & 0x7f;
+ n = (reg >> 8) & 0x1f;
+ p = (reg >> 16) & 0x3f;
+ r = (reg >> 24) & 0x3f;
+
+ /*pll databook*/
+ if (m<4)
+ m=128+m;
+
+ if (m==0xb)
+ m=0xa;
+
+ shift = ffs(pllpr->covpr_mask)-1;
+ reg = fh_pmu_get_reg(pllpr->reg_ctrl1);
+
+ switch ((reg&pllpr->covpr_mask)>>shift){
+ case DIVVCO_ONE_DEVISION:
+ divvcop = 1;
+ break;
+
+ case DIVVCO_TWO_DEVISION:
+ divvcop = 2;
+ break;
+
+ case DIVVCO_FOUR_DEVISION:
+ divvcop = 4;
+ break;
+
+ case DIVVCO_EIGHT_DEVISION:
+ divvcop = 8;
+ break;
+
+ case DIVVCO_SIXTEEN_DEVISION:
+ divvcop = 16;
+ break;
+
+ case DIVVCO_THIRTYTWO_DEVISION:
+ divvcop = 32;
+ break;
+ default:
+ pr_err("divvcop error:%x\n", divvcop);
+ }
+
+ clk_vco = parent_rate * m / (n+1);
+ if (pllpr->flag & CLOCK_PLL_P)
+ rate = clk_vco / (p+1) / divvcop;
+ else
+ rate = clk_vco / (r+1) / divvcop;
+ return rate;
+}
+static const struct clk_ops clk_pll_pr_ops = {
+ .recalc_rate = fh_clk_get_pll_pr_rate,
+};
+
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned int m = 0, n = 0, no = 1;
+ u32 reg;
+ u32 rate;
+ struct fh_clk_divider *div = (struct fh_clk_divider *)hw;
+
+ /* Fetch the register value */
+ reg = fh_pmu_get_reg(div->reg);
+ m = reg & 0xff;
+ n = ((reg & (0xf00)) >> 8);
+ no = ((reg & (0x30000)) >> 16);
+ rate = ((parent_rate) * m / n) >> no;
+ return rate;
+
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+ {
+ unsigned int m = 0, n = 0, no = 1;
+ u32 reg;
+ struct fh_clk_divider *div = (struct fh_clk_divider *)hw;
+
+ /* Fetch the register value */
+ reg = fh_pmu_get_reg(div->reg);
+ m = reg & 0xff;
+ n = ((reg & (0xf00)) >> 8);
+ no = ((reg & (0x30000)) >> 16);
+ rate = ((*parent_rate) * m / n) >> no;
+ return rate;
+
+ }
+
+
+static const struct clk_ops clk_pll_ops = {
+ .recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_round_rate,
+};
+
+int fh_pll_clk_register(struct fh_clk *fh_clk)
+{
+ struct clk *clk;
+ const char *clk_name = fh_clk->name;
+ const char *parents[CLOCK_MAX_PARENT];
+ struct fh_clk_divider *div = NULL;
+ int i = 0;
+
+ /* if we have a mux, we will have >1 parents */
+ while (i < CLOCK_MAX_PARENT && fh_clk->parent[i] != NULL) {
+ parents[i] = fh_clk->parent[i]->name;
+ i++;
+ }
+ div = kzalloc(sizeof(struct fh_clk_divider), GFP_KERNEL);
+ if (!div)
+ return 0;
+ div->reg = fh_clk->div_reg_offset;
+ clk = clk_register_composite(NULL, clk_name,
+ parents, i,
+ NULL, NULL,
+ &div->hw, &clk_pll_ops,
+ NULL, NULL, CLK_IGNORE_UNUSED);
+ if (!IS_ERR(clk))
+ clk_register_clkdev(clk, clk_name, NULL);
+ return 1;
+
+}
+
+int fh_pll_pr_clk_register(struct fh_clk *fh_clk)
+{
+ struct clk *clk;
+ const char *clk_name = fh_clk->name;
+ const char *parents[CLOCK_MAX_PARENT];
+ struct fh_clk_pllpr *pll_ctrl = NULL;
+ int i = 0;
+
+ /* if we have a mux, we will have >1 parents */
+ while (i < CLOCK_MAX_PARENT && fh_clk->parent[i] != NULL) {
+ parents[i] = fh_clk->parent[i]->name;
+ i++;
+ }
+ pll_ctrl = kzalloc(sizeof(struct fh_clk_pllpr), GFP_KERNEL);
+ if (!pll_ctrl)
+ return 0;
+ pll_ctrl->reg_ctrl0 = fh_clk->div_reg_offset;
+ pll_ctrl->reg_ctrl1 = fh_clk->en_reg_offset;
+ pll_ctrl->covpr_mask = fh_clk->en_reg_mask;
+ pll_ctrl->flag = fh_clk->flag;
+ clk = clk_register_composite(NULL, clk_name,
+ parents, i,
+ NULL, NULL,
+ &pll_ctrl->hw, &clk_pll_pr_ops,
+ NULL, NULL, CLK_IGNORE_UNUSED);
+ if (!IS_ERR(clk))
+ clk_register_clkdev(clk, clk_name, NULL);
+ return 1;
+
+}
+
+static int fh_clk_set_phase(struct clk_hw *hw,
+ int degree)
+{
+ u32 reg;
+ struct fh_clk_phase *phase = (struct fh_clk_phase *)hw;
+ unsigned long flags = 0;
+ u32 local_degree = 0;
+ u32 shift = 0;
+
+ /*printk("fh_clk_set_phase:%d\n",degree);*/
+ if (phase->lock)
+ spin_lock_irqsave(phase->lock, flags);
+
+ /* Fetch the register value */
+ reg = fh_pmu_get_reg(phase->reg);
+
+ local_degree = degree;
+
+ shift = ffs(phase->mux)-1;
+
+ reg |= (local_degree << shift);
+
+ /* Apply them now */
+ fh_pmu_set_reg(phase->reg, reg);
+ if (phase->lock)
+ spin_unlock_irqrestore(phase->lock, flags);
+
+ return 1;
+}
+
+static int fh_clk_get_phase(struct clk_hw *hw)
+{
+ u32 reg;
+ struct fh_clk_phase *phase = (struct fh_clk_phase *)hw;
+ unsigned long flags = 0;
+ u32 local_degree = 0;
+ u32 shift;
+
+ if (phase->lock)
+ spin_lock_irqsave(phase->lock, flags);
+
+ /* Fetch the register value */
+ reg = fh_pmu_get_reg(phase->reg);
+ shift = ffs(phase->mux)-1;
+
+ reg = reg&(phase->mux) >> shift;
+ local_degree = reg;
+
+ /*printk("fh_clk_get_phase:%d\n",local_degree);*/
+
+ if (phase->lock)
+ spin_unlock_irqrestore(phase->lock, flags);
+
+ return local_degree;
+}
+
+
+static const struct clk_ops fh_clk_phase_ops = {
+ .set_phase = fh_clk_set_phase,
+ .get_phase = fh_clk_get_phase,
+};
+
+int fh_phase_clk_register(struct fh_clk *fh_clk)
+{
+ struct clk *clk;
+ const char *clk_name = fh_clk->name;
+ const char *parents[CLOCK_MAX_PARENT];
+ struct fh_clk_phase *clk_phase = NULL;
+ int i = 0;
+ struct clk_init_data *init = NULL;
+
+ /* if we have a mux, we will have >1 parents */
+ while (i < CLOCK_MAX_PARENT && fh_clk->parent[i] != NULL) {
+ parents[i] = fh_clk->parent[i]->name;
+ i++;
+ }
+ clk_phase = kzalloc(sizeof(struct fh_clk_phase), GFP_KERNEL);
+ if (!clk_phase)
+ return 0;
+ clk_phase->mux = fh_clk->sel_reg_mask;
+ init = kzalloc(sizeof(struct clk_init_data), GFP_KERNEL);
+
+ /* set up gate properties */
+ clk_phase->reg = fh_clk->sel_reg_offset;
+ clk_phase->lock = &clocks_lock;
+ init->ops = &fh_clk_phase_ops;
+ init->parent_names = parents;
+ init->num_parents = i;
+ init->name = clk_name;
+ clk_phase->hw.init = init;
+ clk = clk_register(NULL, &clk_phase->hw);
+ if (!IS_ERR(clk)) {
+ clk_register_clkdev(clk, clk_name, NULL);
+ }
+ return 1;
+
+}
+
+
+int fh_fix_clk_register(struct fh_clk *fh_clk)
+{
+ struct clk *clk;
+ u32 out_values = fh_clk->frequency;
+ const char *clk_name = fh_clk->name;
+
+ clk = clk_register_fixed_rate(NULL, clk_name,
+ NULL,
+ CLK_IS_ROOT,
+ out_values);
+ if (!IS_ERR(clk)) {;
+ clk_register_clkdev(clk, clk_name, NULL);
+ }
+ return 0;
+}
+
+static unsigned long fh_clk_divide_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ u32 divide = 0;
+ struct fh_clk_divider *factors = (struct fh_clk_divider *)hw;
+ unsigned long rate;
+ unsigned long shift;
+ unsigned long flags = 0;
+
+ if (factors->lock)
+ spin_lock_irqsave(factors->lock, flags);
+ if (factors->div_flag) {
+ /* Fetch the register value */
+ reg = fh_pmu_get_reg(factors->reg);
+
+ /* Get each individual factor if applicable */
+ shift = ffs(factors->div_reg_mask)-1;
+ divide = (factors->div_reg_mask & reg)>> shift;
+
+ /* Calculate the rate */
+ rate = (parent_rate) / (divide+1) / factors->prediv;
+ } else
+ rate = parent_rate / factors->prediv;
+ if (factors->lock)
+ spin_unlock_irqrestore(factors->lock, flags);
+
+ return rate;
+}
+
+static long fh_clk_divide_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u32 reg;
+ u32 rount_rate = 0, divide;
+ struct fh_clk_divider *factors = (struct fh_clk_divider *)hw;
+ unsigned long flags = 0;
+
+ if (factors->lock)
+ spin_lock_irqsave(factors->lock, flags);
+
+ if (factors->div_flag) {
+
+ /* Fetch the register value */
+ reg = fh_pmu_get_reg(factors->reg);
+
+ /* Calculate the rate */
+ divide = (*parent_rate) / factors->prediv / rate;
+ rount_rate = (*parent_rate) / divide / factors->prediv;
+ } else
+ pr_err("fh_clk_divide_round_rate not support divide\n");
+
+ if (factors->lock)
+ spin_unlock_irqrestore(factors->lock, flags);
+
+ return rount_rate;
+}
+
+static int fh_clk_divide_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ struct fh_clk_divider *factors = (struct fh_clk_divider *)hw;
+ u32 divide = 0;
+ unsigned long flags = 0;
+ unsigned long shift = 0;
+
+ if (factors->lock)
+ spin_lock_irqsave(factors->lock, flags);
+
+
+ if (factors->div_flag) {
+
+ /* Fetch the register value */
+ reg = fh_pmu_get_reg(factors->reg);
+
+ divide = parent_rate/rate/factors->prediv - 1;
+ /*printk("fh_clk_divide_set_rate:%x\n",divide);*/
+
+ shift = ffs(factors->div_reg_mask)-1;
+
+
+ reg &= ~(factors->div_reg_mask);
+ reg |= ((divide << shift) & factors->div_reg_mask);
+
+ /* Apply them now */
+ fh_pmu_set_reg(factors->reg,reg);
+
+ }
+ if (factors->lock)
+ spin_unlock_irqrestore(factors->lock, flags);
+
+ return 0;
+}
+
+
+static const struct clk_ops fh_clk_divider_ops = {
+ .recalc_rate = fh_clk_divide_recalc_rate,
+ .round_rate = fh_clk_divide_round_rate,
+ .set_rate = fh_clk_divide_set_rate,
+};
+
+int fh_complex_clk_register(struct fh_clk *fh_clk)
+{
+ struct clk *clk;
+ struct clk_gate *gate = NULL;
+ struct clk_hw *clk_mux_hw = NULL;
+ struct clk_mux *mux = NULL;
+ struct clk_hw *clk_gate_hw = NULL;
+ struct fh_clk_divider *div = NULL;
+ struct clk_hw *clk_divider_hw = NULL;
+ const char *clk_name;
+ const char *parents[CLOCK_MAX_PARENT];
+ int i = 0;
+
+ /* if we have a mux, we will have >1 parents */
+ while (i < CLOCK_MAX_PARENT && fh_clk->parent[i] != NULL) {
+ parents[i] = fh_clk->parent[i]->name;
+ i++;
+ }
+
+ clk_name = fh_clk->name;
+ /* Leaves can be fixed or configurable divisors */
+ if ((!(fh_clk->flag & CLOCK_NODIV)) || (fh_clk->prediv > 1)) {
+ div = kzalloc(sizeof(struct fh_clk_divider), GFP_KERNEL);
+ if (!div)
+ return 0;
+ clk_divider_hw = &div->hw;
+ div->reg = fh_clk->div_reg_offset;
+ if(!(fh_clk->flag & CLOCK_NODIV))
+ div->div_flag = 1;
+ div->div_reg_mask = fh_clk->div_reg_mask;
+ div->prediv = fh_clk->prediv;
+ div->lock = &clocks_lock;
+ }
+
+ /* Add a gate if this factor clock can be gated */
+ if (!(fh_clk->flag & CLOCK_NOGATE)) {
+ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(div);
+ return 0;
+ }
+ /* set up gate properties */
+ gate->reg = (void __iomem *)(fh_clk->en_reg_offset + VA_PMU_REG_BASE);
+ gate->bit_idx =ffs(fh_clk->en_reg_mask)-1;
+ gate->lock = &clocks_lock;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ clk_gate_hw = &gate->hw;
+ }
+
+ if (fh_clk->flag & CLOCK_MULTI_PARENT) {
+ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+
+
+ /* set up gate properties */
+ mux->reg = (void __iomem *)(fh_clk->sel_reg_offset + VA_PMU_REG_BASE);
+ mux->shift = ffs(fh_clk->sel_reg_mask)-1;
+ mux->mask = fh_clk->sel_reg_mask>>mux->shift;
+ mux->lock = &clocks_lock;
+ clk_mux_hw = &mux->hw;
+ }
+ clk = clk_register_composite(NULL, clk_name,
+ parents, i,
+ clk_mux_hw, &clk_mux_ops,
+ clk_divider_hw, &fh_clk_divider_ops,
+ clk_gate_hw, &clk_gate_ops, CLK_IGNORE_UNUSED);
+ if (!IS_ERR(clk)) {
+ clk_register_clkdev(clk, clk_name, NULL);
+ }
+ return 1;
+}
+
+
+int fh_clk_register(struct fh_clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ if(clk->flag & CLOCK_PLL) {
+ fh_pll_clk_register(clk);
+ return 0;
+ }
+ if(clk->flag & (CLOCK_PLL_P|CLOCK_PLL_R)) {
+ fh_pll_pr_clk_register(clk);
+ return 0;
+ }
+ if(clk->flag & CLOCK_FIXED) {
+ fh_fix_clk_register(clk);
+ return 0;
+ }
+ if(clk->flag & CLOCK_PHASE) {
+ fh_phase_clk_register(clk);
+ return 0;
+ }
+ fh_complex_clk_register(clk);
+ return 0;
+}
+EXPORT_SYMBOL(fh_clk_register);
+
+
+static void del_char(char* str, char ch)
+{
+ char *p = str;
+ char *q = str;
+ while (*q) {
+ if (*q != ch) {
+ *p++ = *q;
+ }
+ q++;
+ }
+ *p = '\0';
+}
+static ssize_t fh_clk_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off)
+{
+ int i, ret;
+ char message[64] = {0};
+ char * const delim = ",";
+ char *cur = message;
+ char *param_str[4];
+ unsigned int param[4];
+ struct clk *clk;
+
+ len = (len > 64) ? 64 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for (i = 0; i < 3; i++) {
+ param_str[i] = strsep(&cur, delim);
+ if (!param_str[i]) {
+ pr_err("%s: ERROR: parameter[%d] is empty\n", __func__, i);
+ pr_err("[clk name], [enable/disable], [clk rate]\n");
+ return -EINVAL;
+ } else {
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ }
+ }
+
+ clk = clk_get(NULL, param_str[0]);
+ if (!clk || IS_ERR(clk)) {
+ pr_err("%s: ERROR: clk %s is not found\n", __func__, param_str[0]);
+ pr_err("[clk name], [enable/disable], [clk rate]\n");
+ return -EINVAL;
+ }
+
+ param[2] = (u32)simple_strtoul(param_str[2], NULL, 10);
+ if (param[2] < 0) {
+ pr_err("ERROR: parameter[2] is incorrect\n");
+ return -EINVAL;
+ }
+
+ if (!strcmp(param_str[1], "enable")) {
+ clk_prepare_enable(clk);
+ printk("clk %s enabled\n", param_str[0]);
+ }
+ else if (!strcmp(param_str[1], "disable")) {
+ clk_disable_unprepare(clk);
+ printk(KERN_ERR "clk %s disabled\n", param_str[0]);
+ return len;
+ } else {
+ pr_err("%s: ERROR: parameter[1]:%s is incorrect\n",
+ __func__, param_str[1]);
+ pr_err("[clk name], [enable/disable], [clk rate]\n");
+ return -EINVAL;
+ }
+
+ ret = clk_set_rate(clk, param[2]);
+ if (ret)
+ pr_err("set clk rate failed\n, ret=%d\n", ret);
+
+ return len;
+}
+
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter = 0;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+
+ struct fh_clk *fh_clk;
+ struct clk *clk;
+ unsigned long rate;
+ unsigned int reg;
+ char gate[10] = {0};
+ int i = 0;
+ seq_printf(sfile, "\nPLL Information: \n");
+ for (; fh_clks[i]; i++) {
+ fh_clk = fh_clks[i];
+ if (fh_clk->flag & CLOCK_HIDE)
+ continue;
+ clk = clk_get(NULL, fh_clk->name);
+ if (clk == NULL || IS_ERR(clk))
+ continue;
+ rate = clk_get_rate(clk);
+ if (!(fh_clk->flag & CLOCK_NOGATE)) {
+ reg = fh_pmu_get_reg(fh_clk->en_reg_offset);
+ reg &= fh_clk->en_reg_mask;
+ if (reg) {
+ if (fh_clk->flag & (CLOCK_PLL_P|CLOCK_PLL_R))
+ strncpy(gate, "enable", sizeof(gate));
+ else
+ strncpy(gate, "disable", sizeof(gate));
+ } else {
+ if (fh_clk->flag & (CLOCK_PLL_P|CLOCK_PLL_R))
+ strncpy(gate, "disable", sizeof(gate));
+ else
+ strncpy(gate, "enable", sizeof(gate));
+ }
+ } else {
+ strncpy(gate, "nogate", sizeof(gate));
+ }
+ seq_printf(sfile, "\t%-20s \t%9luHZ \t%-10s\n",
+ fh_clk->name, rate, gate);
+ clk_put(clk);
+}
+ return 0;
+}
+
+static const struct seq_operations fh_clk_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_clk_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &fh_clk_seq_ops);
+}
+
+
+static struct file_operations fh_clk_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_clk_proc_open,
+ .read = seq_read,
+ .write = fh_clk_proc_write,
+ .release = seq_release,
+};
+
+int __init fh_clk_procfs_init(void)
+{
+ proc_file = proc_create(PROC_FILE, 0644, NULL, &fh_clk_proc_ops);
+ if (!proc_file)
+ pr_err("clock, create proc fs failed\n");
+
+ return 0;
+}
+module_init(fh_clk_procfs_init);
+
+int __init fh_clk_init(void)
+{
+ struct fh_clk *fh_clk;
+ struct clk *clk;
+ int i = 0;
+ for (; fh_clks[i]; i++) {
+ fh_clk = fh_clks[i];
+ fh_clk_register(fh_clk);
+ if (fh_clk->def_rate) {
+ clk = clk_get(NULL, fh_clk->name);
+ if(clk && !IS_ERR(clk)) {
+ clk_set_rate(clk, fh_clk->def_rate);
+ clk_put(clk);
+ }
+ }
+ }
+ return 0;
+}
diff --git a/arch/arm/mach-fh/core.h b/arch/arm/mach-fh/core.h
new file mode 100644
index 00000000..1ac9a11d
--- /dev/null
+++ b/arch/arm/mach-fh/core.h
@@ -0,0 +1,24 @@
+#ifndef __HISILICON_CORE_H
+#define __HISILICON_CORE_H
+
+#include <linux/reboot.h>
+
+#define MPCORE_COH_MAGIC 0x434f484d
+#define COH_MAGIC (0x0500)
+#define COH_FUN_BASE (0x0504)
+#define COH_FUN_PARAM (0x0508)
+
+#define OFFSET_LOWPOWER_CTRL (0x109c)
+
+extern void fhca7_set_cpu_jump(int cpu, void *jump_addr);
+extern int fhca7_get_cpu_jump(int cpu);
+extern void secondary_startup(void);
+
+extern void fhca7_cpu_die(unsigned int cpu);
+extern int fhca7_cpu_kill(unsigned int cpu);
+extern void fhca7_set_cpu(int cpu, bool enable);
+
+extern void fhca7_wakeup_cpu(unsigned int cpu);
+extern void fhca7_shutdown_cpu(unsigned int cpu);
+
+#endif
diff --git a/arch/arm/mach-fh/cpuidle.c b/arch/arm/mach-fh/cpuidle.c
new file mode 100644
index 00000000..45668ba3
--- /dev/null
+++ b/arch/arm/mach-fh/cpuidle.c
@@ -0,0 +1,215 @@
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/system_misc.h>
+#include "core.h"
+
+enum {
+ CPU_OP_NONE = 0,
+ CPU_OP_DOWN = 1,
+ CPU_OP_UP = 2,
+};
+
+static int wait_for_cpu_up(unsigned int cpu);
+static void cpu_op_task(struct work_struct *work);
+
+static void __iomem *pmu_base;
+static void __iomem *intc_base;
+static DECLARE_WORK(cpu_op_wq, cpu_op_task);
+static atomic_t fh_cpu_op = ATOMIC_INIT(CPU_OP_NONE);
+
+void fhca7_wakeup_cpu(unsigned int cpu)
+{
+ if (!pmu_base)
+ return;
+
+ if (atomic_read(&fh_cpu_op) == CPU_OP_NONE && cpu_is_offline(cpu)) {
+ pr_debug("cpu%u up\n", cpu);
+ atomic_set(&fh_cpu_op, CPU_OP_UP);
+ schedule_work_on(0, &cpu_op_wq);
+ }
+}
+
+void fhca7_shutdown_cpu(unsigned int cpu)
+{
+ if (!pmu_base)
+ return;
+
+ if (atomic_read(&fh_cpu_op) == CPU_OP_NONE && cpu_active(cpu)) {
+ pr_debug("cpu%u down\n", cpu);
+ atomic_set(&fh_cpu_op, CPU_OP_DOWN);
+ schedule_work_on(0, &cpu_op_wq);
+ }
+}
+
+int fhca7_force_cpu_poweron(unsigned int cpu)
+{
+ int ret = 0;
+
+ if (fhca7_get_cpu_jump(cpu) == 0)
+ return -EBUSY;
+
+ /* force up */
+ writel(0x00079444, pmu_base + OFFSET_LOWPOWER_CTRL);
+
+ /* wait for cpu poweron and init done */
+ ret = wait_for_cpu_up(cpu);
+
+ if (ret)
+ pr_err("cpu%u poweron fail, timeout %d\n", cpu, ret);
+
+ writel(0, pmu_base + OFFSET_LOWPOWER_CTRL);
+ return ret;
+}
+
+void fhca7_wakeup_cpu_force(unsigned int cpu)
+{
+ if (pmu_base && cpu_is_offline(cpu)) {
+ if (!fhca7_force_cpu_poweron(cpu))
+ fhca7_wakeup_cpu(cpu);
+ }
+}
+
+static inline void fhca7_sencondary_cpu_do_idle(unsigned int cpu)
+{
+ fhca7_shutdown_cpu(cpu);
+ cpu_do_idle();
+}
+
+static inline void fhca7_cpu0_do_idle(unsigned int cpu)
+{
+ cpu_do_idle();
+}
+
+static void fhca7_cpu_idle(void)
+{
+ unsigned int cpu = smp_processor_id();
+ if (cpu == 0)
+ fhca7_cpu0_do_idle(cpu);
+ else
+ fhca7_sencondary_cpu_do_idle(cpu);
+}
+
+static int wait_for_cpu_up(unsigned int cpu)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+ while (fhca7_get_cpu_jump(cpu)) {
+ if (time_after(jiffies, timeout))
+ return -1;
+ msleep(1);
+ }
+
+ return 0;
+}
+
+static void cpu_op_task(struct work_struct *work)
+{
+ int cpu = 1;
+ int ret = 0;
+ int cpu_op = atomic_read(&fh_cpu_op);
+
+ if (cpu_op == CPU_OP_DOWN && cpu_active(cpu)) {
+ ret = cpu_down(cpu);
+ if (!ret) {
+ atomic_set(&fh_cpu_op, CPU_OP_NONE);
+ /* enable core 1 int wakeup */
+ writel(0x00078444, pmu_base + OFFSET_LOWPOWER_CTRL);
+ } else {
+ pr_err("cpu%d down error %d\n", cpu, ret);
+ return;
+ }
+ }
+ else if (cpu_op == CPU_OP_UP && cpu_is_offline(cpu)) {
+ if (wait_for_cpu_up(cpu)) {
+ pr_err("wait for cpu%u up timeout\n", cpu);
+ return;
+ }
+ /* disable core 1 int wakeup */
+ writel(0, pmu_base + OFFSET_LOWPOWER_CTRL);
+ ret = cpu_up(cpu);
+ if (!ret) {
+ atomic_set(&fh_cpu_op, CPU_OP_NONE);
+ }
+ else {
+ pr_err("cpu%d up error %d\n", cpu, ret);
+ writel(0x00078444, pmu_base + OFFSET_LOWPOWER_CTRL);
+ return;
+ }
+ }
+}
+
+static int fhca7_cpuidle_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ fhca7_cpu_idle();
+ return index;
+}
+
+static struct cpuidle_driver fhca7_cpuidle_driver = {
+ .name = "fhca7_cpuidle",
+ .owner = THIS_MODULE,
+ .states[0] = {
+ .enter = fhca7_cpuidle_enter,
+ .exit_latency = 2,
+ .target_residency = 1,
+ .name = "fhca7 SRPG",
+ .desc = "CPU powered off",
+ },
+ .state_count = 1,
+};
+
+static int __init fhca7_cpuidle_init(void)
+{
+ struct device_node *node, *idle_node;
+ struct clk *clk;
+
+ node = of_find_compatible_node(NULL, NULL, "fh,fh-pmu");
+ if (!node) {
+ return -ENOENT;
+ }
+
+ pmu_base = of_iomap(node, 0);
+ of_node_put(node);
+ if (!pmu_base) {
+ return -ENOMEM;
+ }
+
+ idle_node = of_find_compatible_node(NULL, NULL, "fh,fh-cpuidle");
+ if (!idle_node) {
+ return -ENOENT;
+ }
+
+ clk = of_clk_get_by_name(idle_node, "intc");
+ if (IS_ERR(clk)) {
+ pr_err("failed to get intc clk\n");
+ return PTR_ERR(clk);
+ }
+ else
+ clk_prepare_enable(clk);
+
+ intc_base = of_iomap(idle_node, 0);
+ of_node_put(idle_node);
+ if (!intc_base) {
+ return -ENOMEM;
+ }
+
+ /* enable timer, wdt int */
+ writel_relaxed(0xc, intc_base);
+
+ arm_pm_idle = fhca7_cpu_idle;
+
+ return cpuidle_register(&fhca7_cpuidle_driver, NULL);
+}
+
+late_initcall(fhca7_cpuidle_init);
diff --git a/arch/arm/mach-fh/fh8852v200/Makefile b/arch/arm/mach-fh/fh8852v200/Makefile
new file mode 100644
index 00000000..1443fdae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v200/Makefile
@@ -0,0 +1 @@
+obj-y += board.o chip.o
\ No newline at end of file
diff --git a/arch/arm/mach-fh/fh8852v200/board.c b/arch/arm/mach-fh/fh8852v200/board.c
new file mode 100644
index 00000000..4d96fee2
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v200/board.c
@@ -0,0 +1,1166 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/phy.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/eeprom.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/if_alg.h>
+#include <linux/mmc/host.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/io.h>
+#include <mach/board_config.h>
+#include <mach/pinctrl.h>
+#include <mach/clock.h>
+#include <mach/fh_uart_plat.h>
+#include <mach/fh_mci_plat.h>
+#include <mach/fh_gmac_plat.h>
+#include <mach/fh_gpio_plat.h>
+#include <mach/fh_efuse_plat.h>
+#include <mach/fh_dma_plat.h>
+#include <mach/fh_spi_plat.h>
+#include <mach/fh_i2s_plat.h>
+#include <mach/fh_pwm_plat.h>
+#include <mach/fh_wdt_plat.h>
+#include <mach/fh_usb_plat.h>
+#include <mach/fh_sadc_plat.h>
+#include <mach/fh_rtc_plat.h>
+#include "chip.h"
+
+struct uart_port fh_serial_ports[FH_UART_NUMBER];
+
+static struct map_desc fh8852v200_io_desc[] = {
+ {
+ .virtual = VA_RAM_REG_BASE,
+ .pfn = __phys_to_pfn(RAM_BASE),
+ .length = SZ_16K,
+ .type = MT_MEMORY_RWX,
+ },
+ {
+ .virtual = VA_DDRC_REG_BASE,
+ .pfn = __phys_to_pfn(DDRC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_INTC_REG_BASE,
+ .pfn = __phys_to_pfn(INTC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_TIMER_REG_BASE,
+ .pfn = __phys_to_pfn(TIMER_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_PMU_REG_BASE,
+ .pfn = __phys_to_pfn(PMU_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART0_REG_BASE,
+ .pfn = __phys_to_pfn(UART0_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART1_REG_BASE,
+ .pfn = __phys_to_pfn(UART1_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART2_REG_BASE,
+ .pfn = __phys_to_pfn(UART2_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+
+};
+
+static struct resource fh_gpio0_resources[] = {
+ {
+ .start = GPIO0_REG_BASE,
+ .end = GPIO0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO0_IRQ,
+ .end = GPIO0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gpio1_resources[] = {
+ {
+ .start = GPIO1_REG_BASE,
+ .end = GPIO1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO1_IRQ,
+ .end = GPIO1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart0_resources[] = {
+ {
+ .start = (UART0_REG_BASE),
+ .end = (UART0_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = UART0_IRQ,
+ .end = UART0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart1_resources[] = {
+ {
+ .start = (UART1_REG_BASE),
+ .end = (UART1_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART1_IRQ,
+ .end = UART1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_uart2_resources[] = {
+ {
+ .start = (UART2_REG_BASE),
+ .end = (UART2_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART2_IRQ,
+ .end = UART2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+static struct resource fh_sdc0_resources[] = {
+ {
+ .start = SDC0_REG_BASE,
+ .end = SDC0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC0_IRQ,
+ .end = SDC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_sdc1_resources[] = {
+ {
+ .start = SDC1_REG_BASE,
+ .end = SDC1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC1_IRQ,
+ .end = SDC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gmac_resources[] = {
+ {
+ .start = GMAC_REG_BASE,
+ .end = GMAC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GMAC_IRQ,
+ .end = GMAC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource fh_wdt_resources[] = {
+ {
+ .start = WDT_REG_BASE,
+ .end = WDT_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = WDT_IRQ,
+ .end = WDT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct resource fh_perf_resources[] = {
+ {
+ .start = PMU_REG_BASE,
+ .end = PMU_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PERF_IRQ,
+ .end = PERF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+
+static struct fh_gmac_platform_data fh_gmac_data = {
+ .phy_reset_pin = 29,
+};
+
+static struct fh_uart_dma uart1_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART1_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART1_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART1_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART1_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+static struct fh_uart_dma uart2_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART2_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART2_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART2_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART2_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+
+static struct fh_platform_uart fh_uart_platform_data[] = {
+ {
+ .mapbase = UART0_REG_BASE,
+ .fifo_size = 16,
+ .irq = UART0_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = NULL,
+ },
+ {
+ .mapbase = UART1_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART1_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart1_dma_info,
+ },
+ {
+ .mapbase = UART2_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART2_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart2_dma_info,
+ },
+};
+
+static struct resource fh_pwm_resources[] = {
+ {
+ .start = PWM_REG_BASE,
+ .end = PWM_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PWM_IRQ,
+ .end = PWM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_i2c_resources_0[] = {
+ {
+ .start = I2C0_REG_BASE,
+ .end = I2C0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C0_IRQ,
+ .end = I2C0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_1[] = {
+ {
+ .start = I2C1_REG_BASE,
+ .end = I2C1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C1_IRQ,
+ .end = I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_2[] = {
+ {
+ .start = I2C2_REG_BASE,
+ .end = I2C2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C2_IRQ,
+ .end = I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_rtc_resources[] = {
+ {
+ .start = RTC_REG_BASE,
+ .end = RTC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio0_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO0",
+ .base = 0,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio1_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO1",
+ .base = 32,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_pwm_data pwm_data = {
+ .npwm = 12,
+};
+
+static struct resource fh_sadc_resources[] = {
+ {
+ .start = SADC_REG_BASE,
+ .end = SADC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SADC_IRQ,
+ .end = SADC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_aes_resources[] = {
+ {
+ .start = AES_REG_BASE,
+ .end = AES_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = AES_IRQ,
+ .end = AES_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_efuse_resources[] = {
+ {
+ .start = EFUSE_REG_BASE,
+ .end = EFUSE_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct resource fh_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+static struct resource fh_axi_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+static struct resource fh_spi0_resources[] = {
+ {
+ .start = SPI0_REG_BASE,
+ .end = SPI0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI0_IRQ,
+ .end = SPI0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi1_resources[] = {
+ {
+ .start = SPI1_REG_BASE,
+ .end = SPI1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI1_IRQ,
+ .end = SPI1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi2_resources[] = {
+ {
+ .start = SPI2_REG_BASE,
+ .end = SPI2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "fh spi2 mem",
+ },
+ {
+ .start = SPI2_IRQ,
+ .end = SPI2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ .name = "fh spi2 irq",
+ },
+};
+
+static struct resource fh_usb_resources[] = {
+ {
+ .start = USBC_REG_BASE,
+ .end = USBC_REG_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USBC_IRQ,
+ .end = USBC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static unsigned int fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+
+struct fh_mci_board fh_mci = {
+ .num_slots = 1,
+ .get_cd = fh_mci_sys_card_detect_fixed,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+ .rescan_max_num = 2,
+};
+
+struct fh_mci_board fh_mci_sd = {
+ .num_slots = 1,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+};
+
+static struct platform_device fh_gmac_device = {
+ .name = "fh_gmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gmac_resources),
+ .resource = fh_gmac_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_gmac_data,
+ },
+};
+
+struct platform_device fh_sd0_device = {
+ .name = "fh_mci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sdc0_resources),
+ .resource = fh_sdc0_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci_sd,
+ }
+};
+
+struct platform_device fh_sd1_device = {
+ .name = "fh_mci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_sdc1_resources),
+ .resource = fh_sdc1_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci,
+ }
+};
+
+struct fh_sadc_platform_data fh_sadc_data = {
+ .ref_vol = 1800,
+ .active_bit = 0xfff,
+};
+
+static struct platform_device fh_sadc_device = {
+ .name = "fh_sadc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sadc_resources),
+ .resource = fh_sadc_resources,
+ .dev = {
+ .platform_data = &fh_sadc_data,
+ },
+};
+
+static struct platform_device fh_uart0_device = {
+ .name = "ttyS",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_uart0_resources),
+ .resource = fh_uart0_resources,
+ .dev.platform_data = &fh_uart_platform_data[0],
+};
+
+static struct platform_device fh_uart1_device = {
+ .name = "ttyS",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_uart1_resources),
+ .resource = fh_uart1_resources,
+ .dev.platform_data = &fh_uart_platform_data[1],
+};
+
+static struct platform_device fh_uart2_device = {
+ .name = "ttyS",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_uart2_resources),
+ .resource = fh_uart2_resources,
+ .dev.platform_data = &fh_uart_platform_data[2],
+};
+
+static struct platform_device fh_pinctrl_device = {
+ .name = "fh_pinctrl",
+ .id = 0,
+};
+
+static struct platform_device fh_i2c0_device = {
+ .name = "fh_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_0),
+ .resource = fh_i2c_resources_0,
+};
+
+static struct platform_device fh_i2c1_device = {
+ .name = "fh_i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_1),
+ .resource = fh_i2c_resources_1,
+};
+
+static struct platform_device fh_i2c2_device = {
+ .name = "fh_i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_2),
+ .resource = fh_i2c_resources_2,
+};
+
+static struct fh_rtc_plat_data rtc_plat_data[] = {
+ {
+ .lut_cof = 58,
+ .lut_offset = 0xff,
+ .tsensor_cp_default_out = 0x993,
+ .clk_name = "rtc_hclk_gate",
+ },
+ {
+ .lut_cof = 71,
+ .lut_offset = 0xf6,
+ .tsensor_cp_default_out = 0x9cc,
+ .clk_name = "rtc_hclk_gate",
+ }
+};
+
+static struct platform_device fh_rtc_device = {
+ .name = "fh_rtc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_rtc_resources),
+ .resource = fh_rtc_resources,
+ .dev.platform_data = &rtc_plat_data[0],
+};
+
+static struct resource fh_i2s_resources[] = {
+ {
+ .start = I2S_REG_BASE,
+ .end = I2S_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ACW_REG_BASE,
+ .end = ACW_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = I2S0_IRQ,
+ .end = I2S0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_i2s_platform_data fh_i2s_data = {
+ .dma_capture_channel = 4,
+ .dma_playback_channel = 5,
+ .dma_master = 0,
+ .dma_rx_hs_num = 10,
+ .dma_tx_hs_num = 11,
+ .clk = "i2s_clk",
+ .acodec_mclk = "ac_clk",
+};
+
+static struct platform_device fh_i2s_device = {
+ .name = "fh_audio",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2s_resources),
+ .resource = fh_i2s_resources,
+ .dev = {
+ .platform_data = &fh_i2s_data,
+ },
+};
+
+static struct platform_device fh_gpio0_device = {
+ .name = GPIO_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gpio0_resources),
+ .resource = fh_gpio0_resources,
+ .dev = {
+ .platform_data = &fh_gpio0_chip,
+ },
+};
+
+static struct platform_device fh_gpio1_device = {
+ .name = GPIO_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_gpio1_resources),
+ .resource = fh_gpio1_resources,
+ .dev = {
+ .platform_data = &fh_gpio1_chip,
+ },
+};
+
+static struct platform_device fh_aes_device = {
+ .name = "fh_aes",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_aes_resources),
+ .resource = fh_aes_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+struct fh_efuse_platform_data fh_efuse_plat_data = {
+ .efuse_support_flag = CRYPTO_CPU_SET_KEY |
+ CRYPTO_EX_MEM_SET_KEY |
+ CRYPTO_EX_MEM_SWITCH_KEY |
+ CRYPTO_EX_MEM_4_ENTRY_1_KEY |
+ CRYPTO_EX_MEM_INDEP_POWER,
+};
+
+
+
+#define FH_SPI0_CS0 (6)
+#define FH_SPI0_CS1 (55)
+
+#define FH_SPI1_CS0 (14)
+#define FH_SPI1_CS1 (57)
+
+#define SPI0_FIFO_DEPTH (128)
+#define SPI0_CLK_IN (200000000)
+#define SPI0_MAX_SLAVE_NO (2)
+#define SPI0_DMA_RX_CHANNEL (0)
+#define SPI0_DMA_TX_CHANNEL (1)
+
+#define SPI1_FIFO_DEPTH (64)
+#define SPI1_CLK_IN (100000000)
+#define SPI1_MAX_SLAVE_NO (2)
+#define SPI1_DMA_RX_CHANNEL (2)
+#define SPI1_DMA_TX_CHANNEL (3)
+
+#define SPI2_CLK_IN (100000000)
+
+/* SPI_TRANSFER_USE_DMA */
+static struct fh_spi_platform_data fh_spi0_data = {
+ .bus_no = 0,
+ .apb_clock_in = SPI0_CLK_IN,
+ .clock_source = {100000000, 150000000, 200000000},
+ .clock_source_num = 3,
+ .slave_max_num = SPI0_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI0_CS0,
+ .cs_data[0].name = "spi0_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI0_CS1,
+ .cs_data[1].name = "spi0_cs1",
+ .clk_name = "spi0_clk",
+ .dma_transfer_enable = SPI_TRANSFER_USE_DMA,
+ .rx_dma_channel = SPI0_DMA_RX_CHANNEL,
+ .rx_handshake_num = 4,
+ /*dma use inc mode could move data by burst mode...*/
+ /*or move data use single mode with low efficient*/
+ .ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |
+ MULTI_WIRE_SUPPORT,
+};
+
+static struct fh_spi_platform_data fh_spi1_data = {
+ .bus_no = 1,
+ .apb_clock_in = SPI1_CLK_IN,
+ .clock_source = {SPI1_CLK_IN},
+ .clock_source_num = 1,
+ .slave_max_num = SPI1_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI1_CS0,
+ .cs_data[0].name = "spi1_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI1_CS1,
+ .cs_data[1].name = "spi1_cs1",
+ .clk_name = "spi1_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct fh_spi_platform_data fh_spi2_data = {
+ .apb_clock_in = SPI2_CLK_IN,
+ .dma_transfer_enable = 0,
+ .rx_handshake_num = 12,
+ .clk_name = "spi2_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct platform_device fh_efuse_device = {
+ .name = "fh_efuse",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_efuse_resources),
+ .resource = fh_efuse_resources,
+ .dev = {
+ .platform_data = &fh_efuse_plat_data,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct fh_dma_platform_data fh_dma_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .nr_channels = 6,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_dma_device = {
+ .name = "fh_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_dma_resources),
+ .resource = fh_dma_resources,
+ .dev = {
+ .platform_data = &fh_dma_data,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+struct fh_axi_dma_platform_data axi_dma_plat_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_axi_dma_device = {
+ .name = "fh_axi_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_axi_dma_resources),
+ .resource = fh_axi_dma_resources,
+ .dev = {
+ .platform_data = &axi_dma_plat_data,
+ },
+};
+#endif
+
+
+
+static struct platform_device fh_spi0_device = {
+ .name = "fh_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi0_resources),
+ .resource = fh_spi0_resources,
+ .dev = {
+ .platform_data = &fh_spi0_data,
+ },
+};
+
+static struct platform_device fh_spi1_device = {
+ .name = "fh_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_spi1_resources),
+ .resource = fh_spi1_resources,
+ .dev = {
+ .platform_data = &fh_spi1_data,
+ },
+};
+
+static struct platform_device fh_spi2_device = {
+ .name = "fh_spi_slave",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi2_resources),
+ .resource = fh_spi2_resources,
+ .dev = {
+ .platform_data = &fh_spi2_data,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct platform_device fh_perf_device = {
+ .name = "fh_perf_mon",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_perf_resources),
+ .resource = fh_perf_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+static struct fh_wdt_platform_data fh_wdt_data = {
+ .mode = MODE_DISCRETE,
+};
+
+struct platform_device fh_wdt_device = {
+ .name = "fh_wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_wdt_resources),
+ .resource = fh_wdt_resources,
+ .dev = {
+ .platform_data = &fh_wdt_data,
+ }
+};
+
+static struct platform_device fh_pwm_device = {
+ .name = "fh_pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_pwm_resources),
+ .resource = fh_pwm_resources,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
+};
+
+static struct fh_usb_platform_data fh_usb_data = {
+ .dr_mode = "host",
+ .vbus_pwren = 47,
+};
+
+struct platform_device fh_usb_device = {
+ .name = "fh_usb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_usb_resources),
+ .resource = fh_usb_resources,
+ .dev = {
+ .platform_data = &fh_usb_data,
+ }
+};
+
+#ifdef CONFIG_FH_TSENSOR
+struct platform_device fh_tsensor_device = {
+ .name = "fh_tsensor",
+ .id = 0,
+};
+#endif
+
+static struct platform_device *fh8852v200_devices[] __initdata = {
+ &fh_uart0_device,
+ &fh_uart1_device,
+ &fh_uart2_device,
+ &fh_pinctrl_device,
+ &fh_i2c0_device,
+ &fh_i2c1_device,
+ &fh_i2c2_device,
+ &fh_rtc_device,
+ &fh_sd0_device,
+ &fh_sd1_device,
+ &fh_sadc_device,
+ &fh_gmac_device,
+ &fh_gpio0_device,
+ &fh_gpio1_device,
+ &fh_aes_device,
+ &fh_efuse_device,
+#ifdef CONFIG_FH_DMAC
+ &fh_dma_device,
+#endif
+#ifdef CONFIG_FH_AXI_DMAC
+ &fh_axi_dma_device,
+#endif
+ &fh_spi0_device,
+ &fh_spi1_device,
+ &fh_spi2_device,
+ &fh_i2s_device,
+ &fh_pwm_device,
+ &fh_wdt_device,
+ &fh_usb_device,
+#ifdef CONFIG_FH_PERF_MON
+ &fh_perf_device,
+#endif
+#ifdef CONFIG_FH_TSENSOR
+ &fh_tsensor_device,
+#endif
+};
+
+static struct mtd_partition fh_sf_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* Ramboot & U-Boot environment */
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* U-Boot */
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi_flash:256k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),4M(kernel),
+ * 8M(rootfs),
+ * -(app) */
+ /* two blocks with bad block table (and mirror) at the end */
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct mtd_partition fh_sf_nand_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_512K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi0.0:64k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),
+ * 4M(kernel),
+ * 8M(rootfs),
+ * -(app)
+ * two blocks with bad block table (and mirror) at the end
+ */
+};
+#endif
+
+static struct flash_platform_data fh_flash_platform_data = {
+ .name = "spi_flash",
+ .parts = fh_sf_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_parts),
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct flash_platform_data fh_nandflash_platform_data = {
+ .name = "spi_nandflash",
+ .parts = fh_sf_nand_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_nand_parts),
+};
+#endif
+
+static struct spi_board_info fh_spi_devices[] = {
+#ifdef CONFIG_MTD_SPI_NAND
+ {
+ .modalias = "spi-nand",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &fh_nandflash_platform_data,
+ },
+#endif
+ {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ /* multi wire should adapt spi para 'ctl_wire_support'*/
+ .mode = SPI_MODE_3 | SPI_RX_DUAL,
+ .max_speed_hz = 50000000,
+ .platform_data = &fh_flash_platform_data,
+ },
+
+};
+
+extern void early_print(const char *str, ...);
+
+static void __init fh_console_pre_init(struct fh_platform_uart *plat, int num)
+{
+ int idx = 0;
+
+ for (; idx < num; idx++) {
+ struct uart_port *port;
+
+ port = &fh_serial_ports[idx];
+ port->mapbase = plat[idx].mapbase;
+ port->fifosize = plat[idx].fifo_size;
+ port->uartclk = plat[idx].uartclk;
+
+ switch (idx) {
+ case 0:
+ port->membase = (unsigned char *)VA_UART0_REG_BASE;
+ break;
+ case 1:
+ port->membase = (unsigned char *)VA_UART1_REG_BASE;
+ break;
+ case 2:
+ port->membase = (unsigned char *)VA_UART2_REG_BASE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void __init fh8852v200_map_io(void)
+{
+ iotable_init(fh8852v200_io_desc, ARRAY_SIZE(fh8852v200_io_desc));
+ fh_console_pre_init(fh_uart_platform_data,
+ ARRAY_SIZE(fh_uart_platform_data));
+}
+
+
+static __init void fh8852v200_board_init(void)
+{
+ if (fh_is_8852v210())
+ fh_rtc_device.dev.platform_data = &rtc_plat_data[1];
+ platform_add_devices(fh8852v200_devices,
+ ARRAY_SIZE(fh8852v200_devices));
+ spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices));
+}
+void __init fh_timer_init_no_of(unsigned int iovbase,
+ unsigned int irqno);
+
+static void __init fh8852v200_init_early(void)
+{
+ fh_pmu_init();
+ fh_pinctrl_init(VA_PMU_REG_BASE + 0x80);
+}
+
+static void __init fh_time_init(void)
+{
+ unsigned int vtimerbase = (unsigned int)ioremap(TIMER_REG_BASE, SZ_4K);
+
+ fh_clk_init();
+ fh_timer_init_no_of(vtimerbase, TMR0_IRQ);
+
+}
+
+void __init fh_intc_init_no_of(unsigned int iovbase);
+static void __init fh_intc_init(void)
+{
+ unsigned int vintcbase = (unsigned int)ioremap(INTC_REG_BASE, SZ_4K);
+
+ fh_intc_init_no_of(vintcbase);
+
+}
+
+static void fh8852v200_restart
+ (enum reboot_mode mode, const char *cmd)
+{
+ fh_pmu_restart();
+}
+
+
+MACHINE_START(FH8852V200, "FH8852V200")
+ .atag_offset = 0x100,
+ .map_io = fh8852v200_map_io,
+ .init_irq = fh_intc_init,
+ .init_time = fh_time_init,
+ .init_machine = fh8852v200_board_init,
+ .init_early = fh8852v200_init_early,
+ .restart = fh8852v200_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-fh/fh8852v200/board_config.fh8852v200.appboard b/arch/arm/mach-fh/fh8852v200/board_config.fh8852v200.appboard
new file mode 100644
index 00000000..02dae328
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v200/board_config.fh8852v200.appboard
@@ -0,0 +1,44 @@
+#ifndef BOARD_CONFIG_H_
+#define BOARD_CONFIG_H_
+
+/*
+ * GPIO0 -> IRCUT_ON
+ * GPIO1 -> IRCUT_OFF
+ * GPIO2 -> USB_PWREN
+ * GPIO11 -> EMAC PHY Reset
+ * GPIO12 -> CIS_CLK
+ * GPIO13 -> CIS_RSTN
+ * GPIO14 -> CIS_PDN
+ * GPIO19 -> SD1_PWREN/WIFI_REG_ON
+ * GPIO20 -> AK7755 Reset
+ * GPIO24 -> LED0
+ * GPIO25 -> LED1
+ * GPIO26 -> Reset Configs
+ * GPIO27 -> AK7755 PowerDown
+ * GPIO28 -> IR
+ * GPIO53 -> USB_PWREN/SD0_PWREN
+ * GPIO55 -> SD1 WIFI Interrupt
+ */
+
+#define CONFIG_SD_CD_FIXED
+
+#define CONFIG_ISP_CLK_RATE 171000000
+#define CONFIG_JPEG_CLK_RATE 171000000
+#define CONFIG_VEU_CLK_RATE 240000000
+
+#define USB_VBUS_PWR_GPIO (47)
+
+#define CONFIG_PINCTRL_SELECT \
+ "ETH", "I2C0", "PWM2", "PWM3", "PWM4", "PWM5", "PWM6", \
+ "PWM7", "PWM8", "PWM9", "SADC_XAIN0", "SADC_XAIN1", \
+ "SD0_NO_WP", "SENSOR_CLK", "SSI0_4BIT", "UART0", \
+ "UART1", "GPIO4", "GPIO13", "GPIO30", "GPIO31", \
+ "GPIO32", "GPIO43", "GPIO44", "GPIO47", \
+\
+ "GPIO11", "GPIO14", "GPIO15", "GPIO16", "GPIO24", \
+ "GPIO25", "GPIO45", "GPIO46", "GPIO48", "GPIO49", \
+ "GPIO50", "GPIO51", "GPIO52", "GPIO53", "GPIO54", \
+ "GPIO55", "GPIO56", "GPIO57", "GPIO58", "GPIO59", \
+ "GPIO60", "GPIO61", "GPIO62", "GPIO63"
+
+#endif /* BOARD_CONFIG_H_ */
diff --git a/arch/arm/mach-fh/fh8852v200/chip.c b/arch/arm/mach-fh/fh8852v200/chip.c
new file mode 100644
index 00000000..9bbb3c49
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v200/chip.c
@@ -0,0 +1,747 @@
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/clock.h>
+#include <mach/board_config.h>
+
+/*
+ * external oscillator
+ * fixed to 24M
+ */
+static struct fh_clk osc_clk = {
+ .name = "osc_clk",
+ .frequency = OSC_FREQUENCY,
+ .flag = CLOCK_FIXED,
+};
+
+/*
+ * phase-locked-loop device,
+ * generates a higher frequency clock
+ * from the external oscillator reference
+ *PLL_DDR
+ */
+
+static struct fh_clk pll_ddr_rclk = {
+ .name = "pll_ddr_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL0,
+ .en_reg_offset = REG_PMU_PLL0_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_CPU*/
+static struct fh_clk pll_cpu_pclk = {
+ .name = "pll_cpu_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+static struct fh_clk pll_cpu_rclk = {
+ .name = "pll_cpu_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_SYS*/
+static struct fh_clk pll_sys_pclk = {
+ .name = "pll_sys_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+
+static struct fh_clk pll_sys_rclk = {
+ .name = "pll_sys_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+static struct fh_clk pllsysp_div12_clk = {
+ .name = "pllsysp_div12_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk ddr_clk = {
+ .name = "ddr_clk",
+ .flag = CLOCK_NODIV,
+ .parent = {&pll_ddr_rclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8,
+};
+static struct fh_clk arm_clk = {
+ .name = "arm_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NOGATE|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1,
+};
+static struct fh_clk arc_clk = {
+ .name = "arc_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400000,
+};
+static struct fh_clk ahb_clk = {
+ .name = "ahb_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&osc_clk, &pll_sys_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf0000,
+};
+
+static struct fh_clk isp_aclk = {
+ .name = "isp_aclk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1,
+ .def_rate = CONFIG_ISP_CLK_RATE,
+};
+static struct fh_clk ispb_aclk = {
+ .name = "ispb_aclk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4,
+};
+
+static struct fh_clk vpu_clk = {
+ .name = "vpu_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80000000,
+};
+
+static struct fh_clk pix_clk = {
+ .name = "pix_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk jpeg_clk = {
+ .name = "jpeg_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x40000000,
+ .def_rate = CONFIG_JPEG_CLK_RATE,
+};
+
+static struct fh_clk bgm_clk = {
+ .name = "bgm_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x40000,
+};
+
+static struct fh_clk jpeg_adapt_clk = {
+ .name = "jpeg_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&jpeg_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2,
+};
+static struct fh_clk spi0_clk = {
+ .name = "spi0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100,
+};
+static struct fh_clk sdc0_clk = {
+ .name = "sdc0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x4,
+};
+static struct fh_clk spi2_clk = {
+ .name = "spi2_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100000,
+};
+static struct fh_clk spi1_clk = {
+ .name = "spi1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x200,
+};
+static struct fh_clk sdc1_clk = {
+ .name = "sdc1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x2,
+};
+
+static struct fh_clk veu_clk = {
+ .name = "veu_clk",
+ .flag = CLOCK_MULTI_PARENT,
+ .parent = {&pll_sys_pclk, &pll_sys_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x4,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0x7000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000000,
+ .def_rate = CONFIG_VEU_CLK_RATE,
+
+};
+
+static struct fh_clk veu_adapt_clk = {
+ .name = "veu_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&veu_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000000,
+
+};
+
+static struct fh_clk cis_clk_out = {
+ .name = "cis_clk_out",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800000,
+};
+
+static struct fh_clk eth_clk = {
+ .name = "eth_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x12000000,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x20000,
+};
+static struct fh_clk i2c0_clk = {
+ .name = "i2c0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400,
+};
+
+static struct fh_clk i2c1_clk = {
+ .name = "i2c1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800,
+};
+
+static struct fh_clk i2c2_clk = {
+ .name = "i2c2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x00003f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x00000008,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20000000,
+};
+
+static struct fh_clk pwm_clk = {
+ .name = "pwm_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x80,
+ .def_rate = 50000000,
+};
+
+static struct fh_clk uart0_clk = {
+ .name = "uart0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x4000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk uart1_clk = {
+ .name = "uart1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000,
+ .def_rate = 16666666,
+};
+static struct fh_clk uart2_clk = {
+ .name = "uart2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = 0,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x7f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk efuse_clk = {
+ .name = "efuse_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800000,
+};
+
+static struct fh_clk pts_clk = {
+ .name = "pts_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = CLOCK_NORESET,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0x1ff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL2,
+ .rst_reg_mask = 0x1,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk tmr0_clk = {
+ .name = "tmr0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x40000,
+};
+
+static struct fh_clk sadc_clk = {
+ .name = "sadc_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x7f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10000,
+};
+
+static struct fh_clk ac_clk = {
+ .name = "ac_clk",
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1000,
+};
+
+static struct fh_clk i2s_clk = {
+ .name = "i2s_clk",
+ .parent = {&ac_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000,
+};
+
+static struct fh_clk wdt_clk = {
+ .name = "wdt_clk",
+ .flag = 0,
+ .parent = {&ahb_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff00,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_APB_CTRL,
+ .rst_reg_mask = 0x100000,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk gpio0_db_clk = {
+ .name = "gpio0_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio1_db_clk = {
+ .name = "gpio1_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff0000,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x80000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20,
+};
+
+
+static struct fh_clk mipi_dphy_clk = {
+ .name = "mipi_dphy_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100000,
+};
+static struct fh_clk mipi_wrap_gate = {
+ .name = "mipi_wrap_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk rtc_hclk_gate = {
+ .name = "rtc_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk emac_hclk_gate = {
+ .name = "emac_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk usb_clk = {
+ .name = "usb_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk aes_hclk_gate = {
+ .name = "aes_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80,
+};
+static struct fh_clk ephy_clk_gate = {
+ .name = "ephy_clk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1,
+};
+static struct fh_clk sdc0_clk8x_gate = {
+ .name = "sdc0_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4,
+};
+static struct fh_clk sdc1_clk8x_gate = {
+ .name = "sdc1_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8,
+};
+static struct fh_clk mipic_pclk_gate = {
+ .name = "mipic_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio0_pclk_gate = {
+ .name = "gpio0_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x4000,
+};
+static struct fh_clk gpio1_pclk_gate = {
+ .name = "gpio1_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x40000000,
+};
+static struct fh_clk isp_hclk_gate = {
+ .name = "isp_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk veu_hclk_gate = {
+ .name = "veu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk bgm_hclk_gate = {
+ .name = "bgm_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x4000000,
+};
+static struct fh_clk adapt_hclk_gate = {
+ .name = "adapt_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x8000000,
+};
+static struct fh_clk jpg_hclk_gate = {
+ .name = "jpg_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk jpg_adapt_gate = {
+ .name = "jpg_adapt_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk vpu_hclk_gate = {
+ .name = "vpu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x40000000,
+};
+
+static struct fh_clk sdc0_clk_sample = {
+ .name = "sdc0_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf0000,
+};
+
+static struct fh_clk sdc0_clk_drv = {
+ .name = "sdc0_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00000,
+};
+
+static struct fh_clk sdc1_clk_sample = {
+ .name = "sdc1_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00,
+};
+
+static struct fh_clk sdc1_clk_drv = {
+ .name = "sdc1_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf000,
+};
+
+struct fh_clk *fh_clks[] = {
+ &osc_clk,
+ &pll_ddr_rclk,
+ &pll_cpu_pclk,
+ &pll_cpu_rclk,
+ &pll_sys_pclk,
+ &pll_sys_rclk,
+ &arm_clk,
+ &arc_clk,
+ &ahb_clk,
+ &ddr_clk,
+ &isp_aclk,
+ &ispb_aclk,
+ &jpeg_clk,
+ &jpeg_adapt_clk,
+ &vpu_clk,
+ &veu_clk,
+ &veu_adapt_clk,
+ &bgm_clk,
+ &mipi_dphy_clk,
+ &pllsysp_div12_clk,
+ &cis_clk_out,
+ &pix_clk,
+ &pts_clk,
+ &spi0_clk,
+ &spi1_clk,
+ &spi2_clk,
+ &sdc0_clk,
+ &sdc1_clk,
+ &uart0_clk,
+ &uart1_clk,
+ &uart2_clk,
+ &i2c0_clk,
+ &i2c1_clk,
+ &i2c2_clk,
+ &pwm_clk,
+ &wdt_clk,
+ &tmr0_clk,
+ &ac_clk,
+ &i2s_clk,
+ &sadc_clk,
+ &eth_clk,
+ &efuse_clk,
+ &gpio0_db_clk,
+ &gpio1_db_clk,
+ &mipi_wrap_gate,
+ &rtc_hclk_gate,
+ &emac_hclk_gate,
+ &usb_clk,
+ &aes_hclk_gate,
+ &ephy_clk_gate,
+ &sdc0_clk8x_gate,
+ &sdc1_clk8x_gate,
+ &gpio0_pclk_gate,
+ &gpio1_pclk_gate,
+ &mipic_pclk_gate,
+ &sdc0_clk_sample,
+ &sdc0_clk_drv,
+ &sdc1_clk_sample,
+ &sdc1_clk_drv,
+ &isp_hclk_gate,
+ &veu_hclk_gate,
+ &bgm_hclk_gate,
+ &adapt_hclk_gate,
+ &jpg_hclk_gate,
+ &jpg_adapt_gate,
+ &vpu_hclk_gate,
+ NULL,
+};
+EXPORT_SYMBOL(fh_clks);
diff --git a/arch/arm/mach-fh/fh8852v200/chip.h b/arch/arm/mach-fh/fh8852v200/chip.h
new file mode 100644
index 00000000..18ff2d65
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v200/chip.h
@@ -0,0 +1,421 @@
+#ifndef __ASM_ARCH_HL_H
+#define __ASM_ARCH_HL_H
+
+#include <linux/init.h>
+
+#define SRAM_GRANULARITY 32
+#define SRAM_SIZE (SZ_128K+SZ_8K)
+
+
+#define RAM_BASE (0x10000000)
+#define DDR_BASE (0xA0000000)
+
+
+#define PMU_REG_BASE (0xF0000000)
+#define TIMER_REG_BASE (0xF0C00000)
+#define GPIO0_REG_BASE (0xF0300000)
+#define GPIO1_REG_BASE (0xF4000000)
+#define UART0_REG_BASE (0xF0700000)
+#define UART1_REG_BASE (0xF0800000)
+#define SPI0_REG_BASE (0xF0500000)
+#define SPI1_REG_BASE (0xF0600000)
+#define SPI2_REG_BASE (0xF0640000)
+#define INTC_REG_BASE (0xE0200000)
+#define GMAC_REG_BASE (0xE0600000)
+#define USBC_REG_BASE (0xE0700000)
+#define DMAC_REG_BASE (0xE0300000)
+#define I2C1_REG_BASE (0xF0B00000)
+#define I2C0_REG_BASE (0xF0200000)
+#define I2C2_REG_BASE (0xF0100000)
+#define SDC0_REG_BASE (0xE2000000)
+#define SDC1_REG_BASE (0xE2200000)
+#define WDT_REG_BASE (0xF0D00000)
+#define PWM_REG_BASE (0xF0400000)
+#define I2S_REG_BASE (0xF0900000)
+#define ACW_REG_BASE (0xF0A00000)
+#define UART2_REG_BASE (0xF1300000)
+#define SADC_REG_BASE (0xF1200000)
+#define EFUSE_REG_BASE (0xF1600000)
+#define AES_REG_BASE (0xE8200000)
+#define RTC_REG_BASE (0xF1500000)
+#define DDRC_REG_BASE (0xED000000)
+#define CONSOLE_REG_BASE UART0_REG_BASE
+#define FH_UART_NUMBER 3
+
+#define FH_PMU_REG_SIZE 0x2110
+#define REG_PMU_CHIP_ID (0x0000)
+#define REG_PMU_IP_VER (0x0004)
+#define REG_PMU_FW_VER (0x0008)
+#define REG_PMU_CLK_SEL (0x000c)
+/*for HL REG_PMU_SYS_CTRL and CLK_SEL use one register */
+#define REG_PMU_SYS_CTRL (0x000c)
+#define REG_PMU_PLL0 (0x0010)
+#define REG_PMU_PLL1 (0x0014)
+#define REG_PMU_PLL0_CTRL (0x0018)
+#define REG_PMU_CLK_GATE (0x001c)
+#define REG_PMU_CLK_GATE1 (0x0020)
+#define REG_PMU_CLK_DIV0 (0x0024)
+#define REG_PMU_CLK_DIV1 (0x0028)
+#define REG_PMU_CLK_DIV2 (0x002c)
+#define REG_PMU_CLK_DIV3 (0x0030)
+#define REG_PMU_CLK_DIV4 (0x0034)
+#define REG_PMU_CLK_DIV5 (0x0038)
+#define REG_PMU_CLK_DIV6 (0x003c)
+#define REG_PMU_SWRST_MAIN_CTRL (0x0040)
+#define REG_PMU_SWRST_MAIN_CTRL2 (0x0044)
+#define REG_PMU_SWRST_AHB_CTRL (0x0048)
+#define REG_PMU_SWRST_APB_CTRL (0x004c)
+#define REG_PMU_SPC_IO_STATUS (0x0054)
+#define REG_PMU_SPC_FUN (0x0058)
+#define REG_PMU_CLK_DIV7 (0x005c)
+#define REG_PMU_CLK_DIV8 (0x0060)
+#define REG_PMU_PLL2 (0x0064)
+#define REG_PMU_PLL2_CTRL (0x0068)
+#define REG_PMU_PLL1_CTRL (0x006c)
+#define REG_PAD_PWR_SEL (0x0074)
+#define REG_PMU_SWRSTN_NSR (0x0078)
+#define REG_PMU_SWRSTN_NSR1 (0x007c)
+#define REG_PMU_ETHPHY_REG0 (0x2108)
+
+
+#define REG_PMU_PAD_BOOT_MODE_CFG (0x0080)
+#define REG_PMU_PAD_BOOT_SEL1_CFG (0x0084)
+#define REG_PMU_PAD_BOOT_SEL0_CFG (0x0088)
+#define REG_PMU_PAD_UART0_TX_CFG (0x008c)
+#define REG_PMU_PAD_UART0_RX_CFG (0x0090)
+#define REG_PMU_PAD_I2C0_SCL_CFG (0x0094)
+#define REG_PMU_PAD_I2C0_SDA_CFG (0x0098)
+#define REG_PMU_PAD_SENSOR_CLK_CFG (0x009c)
+#define REG_PMU_PAD_SENSOR_RSTN_CFG (0x00a0)
+#define REG_PMU_PAD_UART1_TX_CFG (0x00a4)
+#define REG_PMU_PAD_UART1_RX_CFG (0x00a8)
+#define REG_PMU_PAD_I2C1_SCL_CFG (0x00ac)
+#define REG_PMU_PAD_I2C1_SDA_CFG (0x00b0)
+#define REG_PMU_PAD_UART2_TX_CFG (0x00b4)
+#define REG_PMU_PAD_UART2_RX_CFG (0x00b8)
+#define REG_PMU_PAD_USB_PWREN_CFG (0x00bc)
+#define REG_PMU_PAD_PWM0_CFG (0x00c0)
+#define REG_PMU_PAD_PWM1_CFG (0x00c4)
+#define REG_PMU_PAD_PWM2_CFG (0x00c8)
+#define REG_PMU_PAD_PWM3_CFG (0x00cc)
+#define REG_PMU_PAD_MAC_RMII_CLK_CFG (0x00d0)
+#define REG_PMU_PAD_MAC_REF_CLK_CFG (0x00d4)
+#define REG_PMU_PAD_MAC_TXD0_CFG (0x00d8)
+#define REG_PMU_PAD_MAC_TXD1_CFG (0x00dc)
+#define REG_PMU_PAD_MAC_TXEN_CFG (0x00e0)
+#define REG_PMU_PAD_MAC_RXD0_CFG (0x00e4)
+#define REG_PMU_PAD_MAC_RXD1_CFG (0x00e8)
+#define REG_PMU_PAD_MAC_RXDV_CFG (0x00ec)
+#define REG_PMU_PAD_MAC_MDC_CFG (0x00f0)
+#define REG_PMU_PAD_MAC_MDIO_CFG (0x00f4)
+#define REG_PMU_PAD_SD1_CLK_CFG (0x00f8)
+#define REG_PMU_PAD_SD1_CD_CFG (0x00fc)
+#define REG_PMU_PAD_SD1_CMD_RSP_CFG (0x0100)
+#define REG_PMU_PAD_SD1_DATA_0_CFG (0x0104)
+#define REG_PMU_PAD_SD1_DATA_1_CFG (0x0108)
+#define REG_PMU_PAD_SD1_DATA_2_CFG (0x010c)
+#define REG_PMU_PAD_SD1_DATA_3_CFG (0x0110)
+#define REG_PMU_PAD_GPIO_0_CFG (0x0114)
+#define REG_PMU_PAD_GPIO_1_CFG (0x0118)
+#define REG_PMU_PAD_GPIO_2_CFG (0x011c)
+#define REG_PMU_PAD_GPIO_3_CFG (0x0120)
+#define REG_PMU_PAD_GPIO_4_CFG (0x0124)
+#define REG_PMU_PAD_SSI0_CLK_CFG (0x0128)
+#define REG_PMU_PAD_SSI0_CSN_0_CFG (0x012c)
+#define REG_PMU_PAD_SSI0_TXD_CFG (0x0130)
+#define REG_PMU_PAD_SSI0_RXD_CFG (0x0134)
+#define REG_PMU_PAD_SSI0_D2_CFG (0x0138)
+#define REG_PMU_PAD_SSI0_D3_CFG (0x013c)
+#define REG_PMU_PAD_SSI1_CLK_CFG (0x0140)
+#define REG_PMU_PAD_SSI1_CSN_0_CFG (0x0144)
+#define REG_PMU_PAD_SSI1_TXD_CFG (0x0148)
+#define REG_PMU_PAD_SSI1_RXD_CFG (0x014c)
+#define REG_PMU_PAD_SD0_CD_CFG (0x0150)
+#define REG_PMU_PAD_SD0_CLK_CFG (0x0154)
+#define REG_PMU_PAD_SD0_CMD_RSP_CFG (0x0158)
+#define REG_PMU_PAD_SD0_DATA_0_CFG (0x015c)
+#define REG_PMU_PAD_SD0_DATA_1_CFG (0x0160)
+#define REG_PMU_PAD_SD0_DATA_2_CFG (0x0164)
+#define REG_PMU_PAD_SD0_DATA_3_CFG (0x0168)
+#define REG_PMU_PAD_SADC_XAIN0_CFG (0x016c)
+#define REG_PMU_PAD_SADC_XAIN1_CFG (0x0170)
+#define REG_PMU_PAD_SADC_XAIN2_CFG (0x0174)
+#define REG_PMU_PAD_SADC_XAIN3_CFG (0x0178)
+#define REG_PMU_PAD_GPIO_28_CFG (0x017c)
+#define REG_PMU_PAD_GPIO_29_CFG (0x0180)
+
+#define REG_PMU_ARM_INT_0 (0x01e0)
+#define REG_PMU_ARM_INT_1 (0x01e4)
+#define REG_PMU_ARM_INT_2 (0x01e8)
+#define REG_PMU_A625_INT_0 (0x01ec)
+#define REG_PMU_A625_INT_1 (0x01f0)
+#define REG_PMU_A625_INT_2 (0x01f4)
+#define REG_PMU_DMA (0x01f8)
+#define REG_PMU_WDT_CTRL (0x01fc)
+#define REG_PMU_DBG_STAT0 (0x0200)
+#define REG_PMU_DBG_STAT1 (0x0204)
+#define REG_PMU_DBG_STAT2 (0x0208)
+#define REG_PMU_DBG_STAT3 (0x020c)
+#define REG_PMU_USB_SYS (0x0210)
+#define REG_PMU_USB_CFG (0x0214)
+#define REG_PMU_USB_TUNE (0x0218)
+#define REG_PMU_USB_SYS1 (0x0228)
+#define REG_PMU_PTSLO (0x022c)
+#define REG_PMU_PTSHI (0x0230)
+#define REG_PMU_USER0 (0x0234)
+#define REG_PMU_BOOT_MODE (0x0330)
+#define REG_PMU_DDR_SIZE (0x0334)
+#define REG_PMU_RESERVED2 (0x0338)
+#define REG_PMU_CHIP_INFO (0x033c)
+#define REG_PMU_EPHY_PARAM (0x0340)
+#define REG_PMU_RTC_PARAM (0x0344)
+#define REG_PMU_SD1_FUNC_SEL (0x03a0)
+#define REG_PMU_PRDCID_CTRL0 (0x0500)
+#define REG_PMU_A625BOOT0 (0x2000)
+#define REG_PMU_A625BOOT1 (0x2004)
+#define REG_PMU_A625BOOT2 (0x2008)
+#define REG_PMU_A625BOOT3 (0x200c)
+#define REG_PMU_A625_START_CTRL (0x2010)
+#define REG_PMU_ARC_INTC_MASK (0x2014)
+
+#define FH_GMAC_AHB_RESET (1<<17)
+#define FH_GMAC_SPEED_100M (1<<24)
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+#define PMU_RXDV_GPIO_SWITCH (REG_PMU_PAD_MAC_RXDV_CFG)
+#define PMU_RXDV_GPIO_MASK (0x0f000000)
+#define PMU_RXDV_GPIO_VAL (0x01000000)
+
+#define PMU_DWI2S_CLK_SEL_REG (REG_PMU_CLK_SEL)
+#define PMU_DWI2S_CLK_SEL_SHIFT (1)
+#define PMU_DWI2S_CLK_DIV_REG (REG_PMU_CLK_DIV6)
+#define PMU_DWI2S_CLK_DIV_SHIFT (0)
+
+/*ATTENTION: written by ARC */
+#define PMU_ARM_INT_MASK (0x01ec)
+#define PMU_ARM_INT_RAWSTAT (0x01f0)
+#define PMU_ARM_INT_STAT (0x01f4)
+
+#define PMU_A625_INT_MASK (0x01e0)
+#define PMU_A625_INT_RAWSTAT (0x01e4)
+#define PMU_A625_INT_STAT (0x01e8)
+
+#define PMU_IRQ 0
+#define DDRC_IRQ 1
+#define WDT_IRQ 2
+#define TMR0_IRQ 3
+#define VEU_IRQ 4
+#define PERF_IRQ 5
+#define VPU_IRQ 9
+#define I2C0_IRQ 11
+#define I2C1_IRQ 12
+#define JPEG_IRQ 13
+#define BGM_IRQ 14
+#define VEU_LOOP_IRQ 15
+#define AES_IRQ 16
+#define MIPIC_IRQ 17
+#define MIPI_WRAP_IRQ 18
+#define ACW_IRQ 19
+#define SADC_IRQ 20
+#define SPI1_IRQ 21
+#define JPEG_LOOP_IRQ 22
+#define DMAC0_IRQ 23
+#define DMAC1_IRQ 24
+#define I2S0_IRQ 25
+#define GPIO0_IRQ 26
+#define SPI0_IRQ 28
+#define ARC_SW_IRQ 29
+#define UART0_IRQ 30
+#define UART1_IRQ 31
+#define ARM_SW_IRQ 32
+#define RTC_IRQ 33
+#define PWM_IRQ 36
+#define SPI2_IRQ 38
+#define USBC_IRQ 39
+#define GPIO1_IRQ 40
+#define UART2_IRQ 41
+#define SDC0_IRQ 42
+#define SDC1_IRQ 43
+#define GMAC_IRQ 44
+#define EPHY_IRQ 45
+#define I2C2_IRQ 46
+#define RTC_ALM_IRQ 47
+#define RTC_CORE_IRQ 48
+/* because chips with some same function in different */
+/* pmu register, use wrap marco to make code to be same */
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+
+#define MEM_START_PHY_ADDR DDR_BASE
+#define MEM_SIZE 0x4000000
+
+
+#define NR_INTERNAL_IRQS (64)
+#define NR_EXTERNAL_IRQS (64)
+/*#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS)*/
+
+/* SWRST_MAIN_CTRL */
+#define CPU_RSTN_BIT (0)
+#define UTMI_RSTN_BIT (1)
+#define DDRPHY_RSTN_BIT (2)
+#define DDRC_RSTN_BIT (3)
+#define GPIO0_DB_RSTN_BIT (4)
+#define GPIO1_DB_RSTN_BIT (5)
+#define PIXEL_RSTN_BIT (6)
+#define PWM_RSTN_BIT (7)
+#define SPI0_RSTN_BIT (8)
+#define SPI1_RSTN_BIT (9)
+#define I2C0_RSTN_BIT (10)
+#define I2C1_RSTN_BIT (11)
+#define ACODEC_RSTN_BIT (12)
+#define I2S_RSTN_BIT (13)
+#define UART0_RSTN_BIT (14)
+#define UART1_RSTN_BIT (15)
+#define SADC_RSTN_BIT (16)
+#define ADAPT_RSTN_BIT (17)
+#define TMR_RSTN_BIT (18)
+#define UART2_RSTN_BIT (19)
+#define SPI2_RSTN_BIT (20)
+#define JPG_ADAPT_RSTN_BIT (21)
+#define ARC_RSTN_BIT (22)
+#define EFUSE_RSTN_BIT (23)
+#define JPG_RSTN_BIT (24)
+#define VEU_RSTN_BIT (25)
+#define VPU_RSTN_BIT (26)
+#define ISP_RSTN_BIT (27)
+#define BGM_RSTN_BIT (28)
+#define I2C2_RSTN_BIT (29)
+#define EPHY_RSTN_BIT (30)
+#define SYS_RSTN_BIT (31)
+
+/* SWRST_AHB_CTRL */
+#define EMC_HRSTN_BIT (0)
+#define SDC1_HRSTN_BIT (1)
+#define SDC0_HRSTN_BIT (2)
+#define AES_HRSTN_BIT (3)
+#define DMAC0_HRSTN_BIT (4)
+#define INTC_HRSTN_BIT (5)
+#define JPEG_ADAPT_HRSTN_BIT (7)
+#define JPEG_HRSTN_BIT (8)
+#define VCU_HRSTN_BIT (9)
+#define VPU_HRSTN_BIT (10)
+#define ISP_HRSTN_BIT (11)
+#define USB_HRSTN_BIT (12)
+#define HRSTN_BIT (13)
+#define EMAC_HRSTN_BIT (17)
+#define DDRC_HRSTN_BIT (19)
+#define DMAC1_HRSTN_BIT (20)
+#define BGM_HRSTN_BIT (22)
+#define ADAPT_HRSTN_BIT (23)
+
+/* SWRST_APB_CTRL */
+#define ACODEC_PRSTN_BIT (0)
+#define I2S_PRSTN_BIT (1)
+#define UART1_PRSTN_BIT (2)
+#define UART0_PRSTN_BIT (3)
+#define SPI0_PRSTN_BIT (4)
+#define SPI1_PRSTN_BIT (5)
+#define GPIO0_PRSTN_BIT (6)
+#define UART2_PRSTN_BIT (7)
+#define I2C2_PRSTN_BIT (8)
+#define I2C0_PRSTN_BIT (9)
+#define I2C1_PRSTN_BIT (10)
+#define TMR_PRSTN_BIT (11)
+#define PWM_PRSTN_BIT (12)
+#define MIPIW_PRSTN_BIT (13)
+#define MIPIC_PRSTN_BIT (14)
+#define RTC_PRSTN_BIT (15)
+#define SADC_PRSTN_BIT (16)
+#define EFUSE_PRSTN_BIT (17)
+#define SPI2_PRSTN_BIT (18)
+#define WDT_PRSTN_BIT (19)
+#define GPIO1_PRSTN_BIT (20)
+
+/* timer clk fpga 1M,soc 50M*/
+#ifdef CONFIG_FPGA
+#define TIMER_CLK (1000000)
+#else
+#define TIMER_CLK (50000000)
+#endif
+
+#define UART1_TX_HW_HANDSHAKE (9)
+#define UART1_RX_HW_HANDSHAKE (8)
+#define UART2_TX_HW_HANDSHAKE (13)
+#define UART2_RX_HW_HANDSHAKE (12)
+#define UART1_DMA_TX_CHAN (4)
+#define UART1_DMA_RX_CHAN (5)
+#define UART2_DMA_TX_CHAN (4)
+#define UART2_DMA_RX_CHAN (5)
+
+/*sdio*/
+#define SIMPLE_0 (0)
+#define SIMPLE_22 (1)
+#define SIMPLE_45 (2)
+#define SIMPLE_67 (3)
+#define SIMPLE_90 (4)
+#define SIMPLE_112 (5)
+#define SIMPLE_135 (6)
+#define SIMPLE_157 (7)
+#define SIMPLE_180 (8)
+#define SIMPLE_202 (9)
+#define SIMPLE_225 (10)
+#define SIMPLE_247 (11)
+#define SIMPLE_270 (12)
+#define SIMPLE_292 (13)
+#define SIMPLE_315 (14)
+#define SIMPLE_337 (15)
+
+
+
+#define SDIO0_RST_BIT (~UL(1<<2))
+#define SDIO0_CLK_RATE (50000000)
+#define SDIO0_CLK_DRV_SHIFT (20)
+#define SDIO0_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO0_CLK_SAM_SHIFT (16)
+#define SDIO0_CLK_SAM_DEGREE (SIMPLE_0)
+
+
+#define SDIO1_RST_BIT (~UL(1<<1))
+#define SDIO1_CLK_RATE (50000000)
+#define SDIO1_CLK_DRV_SHIFT (12)
+#define SDIO1_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO1_CLK_SAM_SHIFT (8)
+#define SDIO1_CLK_SAM_DEGREE (SIMPLE_0)
+
+#define SDC0_HRSTN (0x1<<2)
+#define SDC1_HRSTN (0x1<<1)
+#define SDC2_HRSTN (0)
+
+
+/*usb*/
+#define IRQ_UHOST USBC_IRQ
+#define FH_PA_OTG USBC_REG_BASE
+#define IRQ_OTG IRQ_UHOST
+#define FH_SZ_USBHOST SZ_1M
+#define FH_SZ_OTG SZ_1M
+
+#define USB_UTMI_RST_BIT (0x1<<1)
+#define USB_PHY_RST_BIT (0x11)
+#define USB_SLEEP_MODE_BIT (0x1<<24)
+#define USB_IDDQ_PWR_BIT (0x1<<10)
+
+
+/* Specific Uart Number */
+#define FH_UART_NUMBER 3
+#define CLK_SCAN_BIT_POS (28)
+#define INSIDE_PHY_ENABLE_BIT_POS (24)
+#define MAC_REF_CLK_DIV_MASK (0x0f)
+#define MAC_REF_CLK_DIV_BIT_POS (24)
+#define MAC_PAD_RMII_CLK_MASK (0x0f)
+#define MAC_PAD_RMII_CLK_BIT_POS (24)
+#define MAC_PAD_MAC_REF_CLK_BIT_POS (28)
+#define ETH_REF_CLK_OUT_GATE_BIT_POS (25)
+#define ETH_RMII_CLK_OUT_GATE_BIT_POS (28)
+#define IN_OR_OUT_PHY_SEL_BIT_POS (26)
+#define INSIDE_CLK_GATE_BIT_POS (0)
+#define INSIDE_PHY_SHUTDOWN_BIT_POS (31)
+#define INSIDE_PHY_RST_BIT_POS (30)
+#define INSIDE_PHY_TRAINING_BIT_POS (27)
+#define INSIDE_PHY_TRAINING_MASK (0x0f)
+
+#define TRAINING_EFUSE_ACTIVE_BIT_POS 4
+
+#endif /* __ASM_ARCH_HL_H */
diff --git a/arch/arm/mach-fh/fh8852v200/iopad.h b/arch/arm/mach-fh/fh8852v200/iopad.h
new file mode 100644
index 00000000..ebc24024
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v200/iopad.h
@@ -0,0 +1,729 @@
+#include <mach/pinctrl.h>
+#include <mach/pinctrl_osdep.h>
+#include <mach/board_config.h>
+
+/* PINCTRL_FUNC */
+PINCTRL_FUNC(GPIO30, 0, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO31, 1, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 1, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO32, 2, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 2, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 2, FUNC2, PUPD_UP, 0);
+PINCTRL_FUNC(UART0_TX, 3, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO33, 3, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART0_RX, 4, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO34, 4, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C0_SCL, 5, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO35, 5, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(I2C0_SDA, 6, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO36, 6, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(SENSOR_CLK, 7, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO12, 7, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO13, 8, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 9, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO39, 9, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 9, FUNC3, PUPD_NONE, 3);
+PINCTRL_FUNC(TEST_O_INT_RMII_CLK, 9, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 10, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO40, 10, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 10, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_0, 10, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 11, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO37, 11, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 11, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 11, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 11, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_1, 11, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 12, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO38, 12, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 12, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 12, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 12, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXEN, 12, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 13, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO41, 13, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM4, 13, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 13, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 13, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_0, 13, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 14, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO42, 14, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM5, 14, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 14, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 14, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_1, 14, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 15, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO47, 15, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 15, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_CRSDV, 15, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM0, 16, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO43, 16, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SCL, 16, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 16, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_0, 16, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM1, 17, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO44, 17, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SDA, 17, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 17, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_1, 17, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 18, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO45, 18, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 19, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO46, 19, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RMII_CLK, 20, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO48, 20, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 20, FUNC2, PUPD_NONE, 3);
+PINCTRL_FUNC(PWM2, 20, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_REF_CLK, 21, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(MAC_TXD_0, 22, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO49, 22, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 22, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM3, 22, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXD_1, 23, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO50, 23, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 23, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM4, 23, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXEN, 24, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO51, 24, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 24, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM5, 24, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_0, 25, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO52, 25, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 25, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM6, 25, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_1, 26, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO53, 26, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 26, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM7, 26, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXDV, 27, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO54, 27, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 27, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM8, 27, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 28, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO55, 28, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 28, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 29, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO56, 29, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 30, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO57, 30, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 30, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 31, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO58, 31, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 31, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO59, 32, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 32, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 33, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO60, 33, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 33, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 34, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO61, 34, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 34, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 35, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO62, 35, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 35, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 36, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO63, 36, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TRSTN, 37, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO0, 37, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DO, 37, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DO, 37, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CLK, 37, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CLK, 37, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADDAT, 37, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM6, 37, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDC, 37, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDO, 38, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO1, 38, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DI, 38, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DI, 38, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CSN_0, 38, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DADAT, 38, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM7, 38, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_I, 38, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDI, 39, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO2, 39, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_CLK, 39, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_CLK, 39, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_TXD, 39, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_TXD, 39, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADBCLK, 39, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM8, 39, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_O, 39, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TCK, 40, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO3, 40, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_WS, 40, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_WS, 40, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_RXD, 40, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_RXD, 40, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADLRC, 40, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 40, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDIO_I, 40, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TMS, 41, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO4, 41, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_MCLK, 41, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 41, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 41, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDC, 41, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI0_CLK, 42, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO5, 42, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CLK, 42, FUNC4, PUPD_NONE, 3);
+PINCTRL_FUNC(SSI0_CSN_0, 43, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO6, 43, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CMD_RSP, 43, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_TXD, 44, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO7, 44, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_0, 44, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_RXD, 45, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO8, 45, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_1, 45, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D2, 46, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO9, 46, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_TX, 46, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SCL, 46, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_2, 46, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D3, 47, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO10, 47, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_RX, 47, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SDA, 47, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_3, 47, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 48, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO11, 48, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CLK, 48, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 49, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CSN_0, 49, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 50, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO15, 50, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_TXD, 50, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 51, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO16, 51, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_RXD, 51, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CD, 52, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO17, 52, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARC_JTAG_TRSTN, 52, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(PAE_JTAG_TRSTN, 52, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD0_CLK, 53, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO18, 53, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 53, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDO, 53, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDO, 53, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CMD_RSP, 54, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO19, 54, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 54, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDI, 54, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDI, 54, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_0, 55, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO20, 55, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 55, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TCK, 55, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TCK, 55, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_1, 56, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO21, 56, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 56, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TMS, 56, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TMS, 56, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_2, 57, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO22, 57, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_TX, 57, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SCL, 57, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DABCLK, 57, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_3, 58, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO23, 58, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 58, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_RX, 58, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SDA, 58, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DALRC, 58, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SADC_XAIN0, 59, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO26, 59, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN1, 60, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO27, 60, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN2, 61, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO24, 61, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN3, 62, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO25, 62, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO28, 63, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 63, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM10, 63, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_DBG_CLK, 63, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 63, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXEN, 63, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 63, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO29, 64, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 64, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM11, 64, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(RTC_CLK, 64, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 64, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_OE, 64, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 64, FUNC7, PUPD_NONE, 0);
+
+
+/* PINCTRL_MUX */
+
+PINCTRL_MUX(AC_I2S_CLK, 0, &PAD39_AC_I2S_CLK);
+PINCTRL_MUX(AC_I2S_DI, 0, &PAD38_AC_I2S_DI);
+PINCTRL_MUX(AC_I2S_DO, 0, &PAD37_AC_I2S_DO);
+PINCTRL_MUX(AC_I2S_WS, 0, &PAD40_AC_I2S_WS);
+PINCTRL_MUX(AC_MCLK, 0, &PAD41_AC_MCLK);
+
+PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD55_ARC_JTAG_TCK);
+PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD54_ARC_JTAG_TDI);
+PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD53_ARC_JTAG_TDO);
+PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD56_ARC_JTAG_TMS);
+PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD52_ARC_JTAG_TRSTN);
+
+PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD40_ARM_JTAG_TCK);
+PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD39_ARM_JTAG_TDI);
+PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD38_ARM_JTAG_TDO);
+PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD41_ARM_JTAG_TMS);
+PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD37_ARM_JTAG_TRSTN);
+
+PINCTRL_MUX(DW_I2S_CLK, 0, &PAD39_DW_I2S_CLK);
+PINCTRL_MUX(DW_I2S_DI, 0, &PAD38_DW_I2S_DI);
+PINCTRL_MUX(DW_I2S_DO, 0, &PAD37_DW_I2S_DO);
+PINCTRL_MUX(DW_I2S_WS, 0, &PAD40_DW_I2S_WS);
+
+PINCTRL_MUX(ETH_LINK_ACT, 1, &PAD1_ETH_LINK_ACT,
+ &PAD63_ETH_LINK_ACT);
+PINCTRL_MUX(ETH_LINK_SPD, 1, &PAD2_ETH_LINK_SPD,
+ &PAD64_ETH_LINK_SPD);
+PINCTRL_MUX(ETH_LINK_STA, 1, &PAD2_ETH_LINK_STA,
+ &PAD64_ETH_LINK_STA);
+
+PINCTRL_MUX(I2C0_SCL, 0, &PAD5_I2C0_SCL);
+PINCTRL_MUX(I2C0_SDA, 0, &PAD6_I2C0_SDA);
+
+PINCTRL_MUX(I2C1_SCL, 2, &PAD11_I2C1_SCL, &PAD30_I2C1_SCL, &PAD46_I2C1_SCL);
+PINCTRL_MUX(I2C1_SDA, 2, &PAD12_I2C1_SDA, &PAD31_I2C1_SDA, &PAD47_I2C1_SDA);
+
+PINCTRL_MUX(I2C2_SCL, 1, &PAD16_I2C2_SCL, &PAD57_I2C2_SCL);
+PINCTRL_MUX(I2C2_SDA, 1, &PAD17_I2C2_SDA, &PAD58_I2C2_SDA);
+
+PINCTRL_MUX(MAC_MDC, 0, &PAD28_MAC_MDC, &PAD63_MAC_MDC);
+PINCTRL_MUX(MAC_MDIO, 0, &PAD29_MAC_MDIO, &PAD64_MAC_MDIO);
+PINCTRL_MUX(MAC_REF_CLK, 0, &PAD21_MAC_REF_CLK);
+PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD20_MAC_RMII_CLK);
+PINCTRL_MUX(MAC_RXDV, 0, &PAD27_MAC_RXDV);
+PINCTRL_MUX(MAC_RXD_0, 0, &PAD25_MAC_RXD_0);
+PINCTRL_MUX(MAC_RXD_1, 0, &PAD26_MAC_RXD_1);
+PINCTRL_MUX(MAC_TXD_0, 0, &PAD22_MAC_TXD_0);
+PINCTRL_MUX(MAC_TXD_1, 0, &PAD23_MAC_TXD_1);
+PINCTRL_MUX(MAC_TXEN, 0, &PAD24_MAC_TXEN);
+
+PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD55_PAE_JTAG_TCK);
+PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD54_PAE_JTAG_TDI);
+PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD53_PAE_JTAG_TDO);
+PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD56_PAE_JTAG_TMS);
+PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD52_PAE_JTAG_TRSTN);
+
+PINCTRL_MUX(PWM0, 0, &PAD16_PWM0);
+PINCTRL_MUX(PWM1, 0, &PAD17_PWM1);
+PINCTRL_MUX(PWM10, 0, &PAD63_PWM10);
+PINCTRL_MUX(PWM11, 0, &PAD64_PWM11);
+PINCTRL_MUX(PWM2, 0, &PAD11_PWM2, &PAD18_PWM2, &PAD20_PWM2);
+PINCTRL_MUX(PWM3, 0, &PAD12_PWM3, &PAD19_PWM3, &PAD22_PWM3);
+PINCTRL_MUX(PWM4, 0, &PAD13_PWM4, &PAD23_PWM4);
+PINCTRL_MUX(PWM5, 0, &PAD14_PWM5, &PAD24_PWM5);
+PINCTRL_MUX(PWM6, 1, &PAD25_PWM6, &PAD37_PWM6);
+PINCTRL_MUX(PWM7, 1, &PAD26_PWM7, &PAD38_PWM7);
+PINCTRL_MUX(PWM8, 1, &PAD27_PWM8, &PAD39_PWM8);
+PINCTRL_MUX(PWM9, 1, &PAD28_PWM9, &PAD40_PWM9);
+
+PINCTRL_MUX(RTC_CLK, 0, &PAD64_RTC_CLK);
+
+PINCTRL_MUX(SADC_XAIN0, 0, &PAD59_SADC_XAIN0);
+PINCTRL_MUX(SADC_XAIN1, 0, &PAD60_SADC_XAIN1);
+PINCTRL_MUX(SADC_XAIN2, 0, &PAD61_SADC_XAIN2);
+PINCTRL_MUX(SADC_XAIN3, 0, &PAD62_SADC_XAIN3);
+
+PINCTRL_MUX(SD0_CD, 0, &PAD52_SD0_CD);
+PINCTRL_MUX(SD0_CLK, 0, &PAD53_SD0_CLK);
+PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD54_SD0_CMD_RSP);
+PINCTRL_MUX(SD0_DATA_0, 0, &PAD55_SD0_DATA_0);
+PINCTRL_MUX(SD0_DATA_1, 0, &PAD56_SD0_DATA_1);
+PINCTRL_MUX(SD0_DATA_2, 0, &PAD57_SD0_DATA_2);
+PINCTRL_MUX(SD0_DATA_3, 0, &PAD58_SD0_DATA_3);
+
+PINCTRL_MUX(SD1_CD, 0, &PAD10_SD1_CD, &PAD22_SD1_CD, &PAD31_SD1_CD,
+ &PAD41_SD1_CD, &PAD63_SD1_CD);
+PINCTRL_MUX(SD1_CLK, 0, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP, 0, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0, 0, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1, 0, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2, 0, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3, 0, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+PINCTRL_MUX(SENSOR_CLK, 0, &PAD7_SENSOR_CLK);
+
+PINCTRL_MUX(SSI0_CLK, 0, &PAD42_SSI0_CLK);
+PINCTRL_MUX(SSI0_D2, 0, &PAD46_SSI0_D2);
+PINCTRL_MUX(SSI0_D3, 0, &PAD47_SSI0_D3);
+PINCTRL_MUX(SSI0_RXD, 0, &PAD45_SSI0_RXD);
+PINCTRL_MUX(SSI0_TXD, 0, &PAD44_SSI0_TXD);
+
+PINCTRL_MUX(SSI1_CLK, 2, &PAD11_SSI1_CLK, &PAD37_SSI1_CLK, &PAD48_SSI1_CLK,
+ &PAD53_SSI1_CLK);
+PINCTRL_MUX(SSI1_RXD, 2, &PAD14_SSI1_RXD, &PAD40_SSI1_RXD, &PAD51_SSI1_RXD,
+ &PAD55_SSI1_RXD);
+PINCTRL_MUX(SSI1_TXD, 2, &PAD13_SSI1_TXD, &PAD39_SSI1_TXD, &PAD50_SSI1_TXD,
+ &PAD54_SSI1_TXD);
+
+PINCTRL_MUX(SSI2_CLK, 1, &PAD37_SSI2_CLK, &PAD48_SSI2_CLK);
+PINCTRL_MUX(SSI2_CSN_0, 1, &PAD38_SSI2_CSN_0, &PAD49_SSI2_CSN_0);
+PINCTRL_MUX(SSI2_RXD, 1, &PAD40_SSI2_RXD, &PAD51_SSI2_RXD);
+PINCTRL_MUX(SSI2_TXD, 1, &PAD39_SSI2_TXD, &PAD50_SSI2_TXD);
+
+PINCTRL_MUX(UART0_RX, 0, &PAD4_UART0_RX);
+PINCTRL_MUX(UART0_TX, 0, &PAD3_UART0_TX);
+
+PINCTRL_MUX(UART1_RX, 0, &PAD10_UART1_RX, &PAD33_UART1_RX, &PAD47_UART1_RX);
+PINCTRL_MUX(UART1_TX, 0, &PAD9_UART1_TX, &PAD32_UART1_TX, &PAD46_UART1_TX);
+
+PINCTRL_MUX(UART2_RX, 0, &PAD14_UART2_RX, &PAD17_UART2_RX, &PAD35_UART2_RX,
+ &PAD58_UART2_RX);
+PINCTRL_MUX(UART2_TX, 0, &PAD13_UART2_TX, &PAD16_UART2_TX, &PAD34_UART2_TX,
+ &PAD57_UART2_TX);
+
+PINCTRL_MUX(USB_PWREN, 0, &PAD15_USB_PWREN, &PAD41_USB_PWREN);
+
+PINCTRL_MUX(GPIO0, 0, &PAD37_GPIO0);
+PINCTRL_MUX(GPIO1, 0, &PAD38_GPIO1);
+PINCTRL_MUX(GPIO2, 0, &PAD39_GPIO2);
+PINCTRL_MUX(GPIO3, 0, &PAD40_GPIO3);
+PINCTRL_MUX(GPIO4, 0, &PAD41_GPIO4);
+PINCTRL_MUX(GPIO5, 0, &PAD42_GPIO5);
+PINCTRL_MUX(GPIO6, 0, &PAD43_GPIO6);
+PINCTRL_MUX(GPIO7, 0, &PAD44_GPIO7);
+PINCTRL_MUX(GPIO8, 0, &PAD45_GPIO8);
+PINCTRL_MUX(GPIO9, 0, &PAD46_GPIO9);
+PINCTRL_MUX(GPIO10, 0, &PAD47_GPIO10);
+PINCTRL_MUX(GPIO11, 0, &PAD48_GPIO11);
+PINCTRL_MUX(GPIO12, 0, &PAD7_GPIO12);
+PINCTRL_MUX(GPIO13, 0, &PAD8_GPIO13);
+PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14);
+PINCTRL_MUX(GPIO15, 0, &PAD50_GPIO15);
+PINCTRL_MUX(GPIO16, 0, &PAD51_GPIO16);
+PINCTRL_MUX(GPIO17, 0, &PAD52_GPIO17);
+PINCTRL_MUX(GPIO18, 0, &PAD53_GPIO18);
+PINCTRL_MUX(GPIO19, 0, &PAD54_GPIO19);
+PINCTRL_MUX(GPIO20, 0, &PAD55_GPIO20);
+PINCTRL_MUX(GPIO21, 0, &PAD56_GPIO21);
+PINCTRL_MUX(GPIO22, 0, &PAD57_GPIO22);
+PINCTRL_MUX(GPIO23, 0, &PAD58_GPIO23);
+PINCTRL_MUX(GPIO24, 0, &PAD61_GPIO24);
+PINCTRL_MUX(GPIO25, 0, &PAD62_GPIO25);
+PINCTRL_MUX(GPIO26, 0, &PAD59_GPIO26);
+PINCTRL_MUX(GPIO27, 0, &PAD60_GPIO27);
+PINCTRL_MUX(GPIO28, 0, &PAD63_GPIO28);
+PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29);
+PINCTRL_MUX(GPIO30, 0, &PAD0_GPIO30);
+PINCTRL_MUX(GPIO31, 0, &PAD1_GPIO31);
+PINCTRL_MUX(GPIO32, 0, &PAD2_GPIO32);
+PINCTRL_MUX(GPIO33, 0, &PAD3_GPIO33);
+PINCTRL_MUX(GPIO34, 0, &PAD4_GPIO34);
+PINCTRL_MUX(GPIO35, 0, &PAD5_GPIO35);
+PINCTRL_MUX(GPIO36, 0, &PAD6_GPIO36);
+PINCTRL_MUX(GPIO37, 0, &PAD11_GPIO37);
+PINCTRL_MUX(GPIO38, 0, &PAD12_GPIO38);
+PINCTRL_MUX(GPIO39, 0, &PAD9_GPIO39);
+PINCTRL_MUX(GPIO40, 0, &PAD10_GPIO40);
+PINCTRL_MUX(GPIO41, 0, &PAD13_GPIO41);
+PINCTRL_MUX(GPIO42, 0, &PAD14_GPIO42);
+PINCTRL_MUX(GPIO43, 0, &PAD16_GPIO43);
+PINCTRL_MUX(GPIO44, 0, &PAD17_GPIO44);
+PINCTRL_MUX(GPIO45, 0, &PAD18_GPIO45);
+PINCTRL_MUX(GPIO46, 0, &PAD19_GPIO46);
+PINCTRL_MUX(GPIO47, 0, &PAD15_GPIO47);
+PINCTRL_MUX(GPIO48, 0, &PAD20_GPIO48);
+PINCTRL_MUX(GPIO49, 0, &PAD22_GPIO49);
+PINCTRL_MUX(GPIO50, 0, &PAD23_GPIO50);
+PINCTRL_MUX(GPIO51, 0, &PAD24_GPIO51);
+PINCTRL_MUX(GPIO52, 0, &PAD25_GPIO52);
+PINCTRL_MUX(GPIO53, 0, &PAD26_GPIO53);
+PINCTRL_MUX(GPIO54, 0, &PAD27_GPIO54);
+PINCTRL_MUX(GPIO55, 0, &PAD28_GPIO55);
+PINCTRL_MUX(GPIO56, 0, &PAD29_GPIO56);
+PINCTRL_MUX(GPIO57, 0, &PAD30_GPIO57);
+PINCTRL_MUX(GPIO58, 0, &PAD31_GPIO58);
+PINCTRL_MUX(GPIO59, 0, &PAD32_GPIO59);
+PINCTRL_MUX(GPIO60, 0, &PAD33_GPIO60);
+PINCTRL_MUX(GPIO61, 0, &PAD34_GPIO61);
+PINCTRL_MUX(GPIO62, 0, &PAD35_GPIO62);
+PINCTRL_MUX(GPIO63, 0, &PAD36_GPIO63);
+
+PINCTRL_MUX(SD1_CLK_EMMC, 3, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP_EMMC, 3, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0_EMMC, 3, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1_EMMC, 3, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2_EMMC, 3, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3_EMMC, 3, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+/* PINCTRL_DEVICE */
+PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO,
+ &MUX_AC_I2S_WS, &MUX_AC_MCLK);
+PINCTRL_DEVICE(AC_MCLK, 1, &MUX_AC_MCLK);
+PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI,
+ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN);
+PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI,
+ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN);
+PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO,
+ &MUX_DW_I2S_WS);
+PINCTRL_DEVICE(ETH, 2, &MUX_ETH_LINK_ACT, &MUX_ETH_LINK_STA);
+PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA);
+PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA);
+PINCTRL_DEVICE(I2C2, 2, &MUX_I2C2_SCL, &MUX_I2C2_SDA);
+PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI,
+ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN);
+PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0);
+PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1);
+PINCTRL_DEVICE(PWM10, 1, &MUX_PWM10);
+PINCTRL_DEVICE(PWM11, 1, &MUX_PWM11);
+PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2);
+PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3);
+PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4);
+PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5);
+PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6);
+PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7);
+PINCTRL_DEVICE(PWM8, 1, &MUX_PWM8);
+PINCTRL_DEVICE(PWM9, 1, &MUX_PWM9);
+PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK,
+ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1,
+ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN);
+PINCTRL_DEVICE(RTC, 1, &MUX_RTC_CLK);
+PINCTRL_DEVICE(SADC_XAIN0, 1, &MUX_SADC_XAIN0);
+PINCTRL_DEVICE(SADC_XAIN1, 1, &MUX_SADC_XAIN1);
+PINCTRL_DEVICE(SADC_XAIN2, 1, &MUX_SADC_XAIN2);
+PINCTRL_DEVICE(SADC_XAIN3, 1, &MUX_SADC_XAIN3);
+PINCTRL_DEVICE(SD0, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0);
+PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_WIFI, 6, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, &MUX_SD0_DATA_0,
+ &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD1, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_1BIT_NO_WP, 4, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0);
+PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_WIFI, 6, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, &MUX_SD1_DATA_0,
+ &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SENSOR_CLK, 1, &MUX_SENSOR_CLK);
+PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_RXD,
+ &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_D2,
+ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI1, 4, &MUX_GPIO14, &MUX_SSI1_CLK, &MUX_SSI1_RXD,
+ &MUX_SSI1_TXD);
+PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN_0, &MUX_SSI2_RXD,
+ &MUX_SSI2_TXD);
+PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX);
+PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX);
+PINCTRL_DEVICE(UART2, 2, &MUX_UART2_RX, &MUX_UART2_TX);
+PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN);
+PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0);
+PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1);
+PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2);
+PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3);
+PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4);
+PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5);
+PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6);
+PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7);
+PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8);
+PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9);
+PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10);
+PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11);
+PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12);
+PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13);
+PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14);
+PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15);
+PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16);
+PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17);
+PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18);
+PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19);
+PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20);
+PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21);
+PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22);
+PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23);
+PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24);
+PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25);
+PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26);
+PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27);
+PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28);
+PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29);
+PINCTRL_DEVICE(GPIO30, 1, &MUX_GPIO30);
+PINCTRL_DEVICE(GPIO31, 1, &MUX_GPIO31);
+PINCTRL_DEVICE(GPIO32, 1, &MUX_GPIO32);
+PINCTRL_DEVICE(GPIO33, 1, &MUX_GPIO33);
+PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34);
+PINCTRL_DEVICE(GPIO35, 1, &MUX_GPIO35);
+PINCTRL_DEVICE(GPIO36, 1, &MUX_GPIO36);
+PINCTRL_DEVICE(GPIO37, 1, &MUX_GPIO37);
+PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38);
+PINCTRL_DEVICE(GPIO39, 1, &MUX_GPIO39);
+PINCTRL_DEVICE(GPIO40, 1, &MUX_GPIO40);
+PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41);
+PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42);
+PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43);
+PINCTRL_DEVICE(GPIO44, 1, &MUX_GPIO44);
+PINCTRL_DEVICE(GPIO45, 1, &MUX_GPIO45);
+PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46);
+PINCTRL_DEVICE(GPIO47, 1, &MUX_GPIO47);
+PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48);
+PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49);
+PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50);
+PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51);
+PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52);
+PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53);
+PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54);
+PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55);
+PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56);
+PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57);
+PINCTRL_DEVICE(GPIO58, 1, &MUX_GPIO58);
+PINCTRL_DEVICE(GPIO59, 1, &MUX_GPIO59);
+PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60);
+PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61);
+PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62);
+PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63);
+
+PINCTRL_DEVICE(SD1_EMMC, 6, &MUX_SD1_CLK_EMMC, &MUX_SD1_CMD_RSP_EMMC,
+ &MUX_SD1_DATA_0_EMMC, &MUX_SD1_DATA_1_EMMC, &MUX_SD1_DATA_2_EMMC,
+ &MUX_SD1_DATA_3_EMMC);
+
+void fh_pinctrl_init_devicelist(OS_LIST *list)
+{
+ OS_LIST_EMPTY(list);
+
+ /*PINCTRL_ADD_DEVICE*/
+ PINCTRL_ADD_DEVICE(ACI2S);
+ PINCTRL_ADD_DEVICE(AC_MCLK);
+ PINCTRL_ADD_DEVICE(ARCJTAG);
+ PINCTRL_ADD_DEVICE(ARMJTAG);
+ PINCTRL_ADD_DEVICE(DWI2S);
+ PINCTRL_ADD_DEVICE(ETH);
+ PINCTRL_ADD_DEVICE(I2C0);
+ PINCTRL_ADD_DEVICE(I2C1);
+ PINCTRL_ADD_DEVICE(I2C2);
+ PINCTRL_ADD_DEVICE(PAEJTAG);
+ PINCTRL_ADD_DEVICE(PWM0);
+ PINCTRL_ADD_DEVICE(PWM1);
+ PINCTRL_ADD_DEVICE(PWM10);
+ PINCTRL_ADD_DEVICE(PWM11);
+ PINCTRL_ADD_DEVICE(PWM2);
+ PINCTRL_ADD_DEVICE(PWM3);
+ PINCTRL_ADD_DEVICE(PWM4);
+ PINCTRL_ADD_DEVICE(PWM5);
+ PINCTRL_ADD_DEVICE(PWM6);
+ PINCTRL_ADD_DEVICE(PWM7);
+ PINCTRL_ADD_DEVICE(PWM8);
+ PINCTRL_ADD_DEVICE(PWM9);
+ PINCTRL_ADD_DEVICE(RMII);
+ PINCTRL_ADD_DEVICE(RTC);
+ PINCTRL_ADD_DEVICE(SADC_XAIN0);
+ PINCTRL_ADD_DEVICE(SADC_XAIN1);
+ PINCTRL_ADD_DEVICE(SADC_XAIN2);
+ PINCTRL_ADD_DEVICE(SADC_XAIN3);
+ PINCTRL_ADD_DEVICE(SD0);
+ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_WIFI);
+ PINCTRL_ADD_DEVICE(SD1);
+ PINCTRL_ADD_DEVICE(SD1_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_WIFI);
+ PINCTRL_ADD_DEVICE(SENSOR_CLK);
+ PINCTRL_ADD_DEVICE(SSI0);
+ PINCTRL_ADD_DEVICE(SSI0_4BIT);
+ PINCTRL_ADD_DEVICE(SSI1);
+ PINCTRL_ADD_DEVICE(SSI2);
+ PINCTRL_ADD_DEVICE(UART0);
+ PINCTRL_ADD_DEVICE(UART1);
+ PINCTRL_ADD_DEVICE(UART2);
+ PINCTRL_ADD_DEVICE(USB);
+ PINCTRL_ADD_DEVICE(GPIO0);
+ PINCTRL_ADD_DEVICE(GPIO1);
+ PINCTRL_ADD_DEVICE(GPIO2);
+ PINCTRL_ADD_DEVICE(GPIO3);
+ PINCTRL_ADD_DEVICE(GPIO4);
+ PINCTRL_ADD_DEVICE(GPIO5);
+ PINCTRL_ADD_DEVICE(GPIO6);
+ PINCTRL_ADD_DEVICE(GPIO7);
+ PINCTRL_ADD_DEVICE(GPIO8);
+ PINCTRL_ADD_DEVICE(GPIO9);
+ PINCTRL_ADD_DEVICE(GPIO10);
+ PINCTRL_ADD_DEVICE(GPIO11);
+ PINCTRL_ADD_DEVICE(GPIO12);
+ PINCTRL_ADD_DEVICE(GPIO13);
+ PINCTRL_ADD_DEVICE(GPIO14);
+ PINCTRL_ADD_DEVICE(GPIO15);
+ PINCTRL_ADD_DEVICE(GPIO16);
+ PINCTRL_ADD_DEVICE(GPIO17);
+ PINCTRL_ADD_DEVICE(GPIO18);
+ PINCTRL_ADD_DEVICE(GPIO19);
+ PINCTRL_ADD_DEVICE(GPIO20);
+ PINCTRL_ADD_DEVICE(GPIO21);
+ PINCTRL_ADD_DEVICE(GPIO22);
+ PINCTRL_ADD_DEVICE(GPIO23);
+ PINCTRL_ADD_DEVICE(GPIO24);
+ PINCTRL_ADD_DEVICE(GPIO25);
+ PINCTRL_ADD_DEVICE(GPIO26);
+ PINCTRL_ADD_DEVICE(GPIO27);
+ PINCTRL_ADD_DEVICE(GPIO28);
+ PINCTRL_ADD_DEVICE(GPIO29);
+ PINCTRL_ADD_DEVICE(GPIO30);
+ PINCTRL_ADD_DEVICE(GPIO31);
+ PINCTRL_ADD_DEVICE(GPIO32);
+ PINCTRL_ADD_DEVICE(GPIO33);
+ PINCTRL_ADD_DEVICE(GPIO34);
+ PINCTRL_ADD_DEVICE(GPIO35);
+ PINCTRL_ADD_DEVICE(GPIO36);
+ PINCTRL_ADD_DEVICE(GPIO37);
+ PINCTRL_ADD_DEVICE(GPIO38);
+ PINCTRL_ADD_DEVICE(GPIO39);
+ PINCTRL_ADD_DEVICE(GPIO40);
+ PINCTRL_ADD_DEVICE(GPIO41);
+ PINCTRL_ADD_DEVICE(GPIO42);
+ PINCTRL_ADD_DEVICE(GPIO43);
+ PINCTRL_ADD_DEVICE(GPIO44);
+ PINCTRL_ADD_DEVICE(GPIO45);
+ PINCTRL_ADD_DEVICE(GPIO46);
+ PINCTRL_ADD_DEVICE(GPIO47);
+ PINCTRL_ADD_DEVICE(GPIO48);
+ PINCTRL_ADD_DEVICE(GPIO49);
+ PINCTRL_ADD_DEVICE(GPIO50);
+ PINCTRL_ADD_DEVICE(GPIO51);
+ PINCTRL_ADD_DEVICE(GPIO52);
+ PINCTRL_ADD_DEVICE(GPIO53);
+ PINCTRL_ADD_DEVICE(GPIO54);
+ PINCTRL_ADD_DEVICE(GPIO55);
+ PINCTRL_ADD_DEVICE(GPIO56);
+ PINCTRL_ADD_DEVICE(GPIO57);
+ PINCTRL_ADD_DEVICE(GPIO58);
+ PINCTRL_ADD_DEVICE(GPIO59);
+ PINCTRL_ADD_DEVICE(GPIO60);
+ PINCTRL_ADD_DEVICE(GPIO61);
+ PINCTRL_ADD_DEVICE(GPIO62);
+ PINCTRL_ADD_DEVICE(GPIO63);
+
+ PINCTRL_ADD_DEVICE(SD1_EMMC);
+}
+
+char *fh_pinctrl_selected_devices[] =
+{
+ CONFIG_PINCTRL_SELECT
+};
diff --git a/arch/arm/mach-fh/fh8852v210/Makefile b/arch/arm/mach-fh/fh8852v210/Makefile
new file mode 100644
index 00000000..1443fdae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v210/Makefile
@@ -0,0 +1 @@
+obj-y += board.o chip.o
\ No newline at end of file
diff --git a/arch/arm/mach-fh/fh8852v210/board.c b/arch/arm/mach-fh/fh8852v210/board.c
new file mode 100644
index 00000000..21655fca
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v210/board.c
@@ -0,0 +1,1166 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/phy.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/eeprom.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/if_alg.h>
+#include <linux/mmc/host.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/io.h>
+#include <mach/board_config.h>
+#include <mach/pinctrl.h>
+#include <mach/clock.h>
+#include <mach/fh_uart_plat.h>
+#include <mach/fh_mci_plat.h>
+#include <mach/fh_gmac_plat.h>
+#include <mach/fh_gpio_plat.h>
+#include <mach/fh_efuse_plat.h>
+#include <mach/fh_dma_plat.h>
+#include <mach/fh_spi_plat.h>
+#include <mach/fh_i2s_plat.h>
+#include <mach/fh_pwm_plat.h>
+#include <mach/fh_wdt_plat.h>
+#include <mach/fh_usb_plat.h>
+#include <mach/fh_sadc_plat.h>
+#include <mach/fh_rtc_plat.h>
+#include "chip.h"
+
+struct uart_port fh_serial_ports[FH_UART_NUMBER];
+
+static struct map_desc fh8852v210_io_desc[] = {
+ {
+ .virtual = VA_RAM_REG_BASE,
+ .pfn = __phys_to_pfn(RAM_BASE),
+ .length = SZ_16K,
+ .type = MT_MEMORY_RWX,
+ },
+ {
+ .virtual = VA_DDRC_REG_BASE,
+ .pfn = __phys_to_pfn(DDRC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_INTC_REG_BASE,
+ .pfn = __phys_to_pfn(INTC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_TIMER_REG_BASE,
+ .pfn = __phys_to_pfn(TIMER_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_PMU_REG_BASE,
+ .pfn = __phys_to_pfn(PMU_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART0_REG_BASE,
+ .pfn = __phys_to_pfn(UART0_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART1_REG_BASE,
+ .pfn = __phys_to_pfn(UART1_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART2_REG_BASE,
+ .pfn = __phys_to_pfn(UART2_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+
+};
+
+static struct resource fh_gpio0_resources[] = {
+ {
+ .start = GPIO0_REG_BASE,
+ .end = GPIO0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO0_IRQ,
+ .end = GPIO0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gpio1_resources[] = {
+ {
+ .start = GPIO1_REG_BASE,
+ .end = GPIO1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO1_IRQ,
+ .end = GPIO1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart0_resources[] = {
+ {
+ .start = (UART0_REG_BASE),
+ .end = (UART0_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = UART0_IRQ,
+ .end = UART0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart1_resources[] = {
+ {
+ .start = (UART1_REG_BASE),
+ .end = (UART1_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART1_IRQ,
+ .end = UART1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_uart2_resources[] = {
+ {
+ .start = (UART2_REG_BASE),
+ .end = (UART2_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART2_IRQ,
+ .end = UART2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+static struct resource fh_sdc0_resources[] = {
+ {
+ .start = SDC0_REG_BASE,
+ .end = SDC0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC0_IRQ,
+ .end = SDC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_sdc1_resources[] = {
+ {
+ .start = SDC1_REG_BASE,
+ .end = SDC1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC1_IRQ,
+ .end = SDC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gmac_resources[] = {
+ {
+ .start = GMAC_REG_BASE,
+ .end = GMAC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GMAC_IRQ,
+ .end = GMAC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource fh_wdt_resources[] = {
+ {
+ .start = WDT_REG_BASE,
+ .end = WDT_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = WDT_IRQ,
+ .end = WDT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct resource fh_perf_resources[] = {
+ {
+ .start = PMU_REG_BASE,
+ .end = PMU_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PERF_IRQ,
+ .end = PERF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+
+static struct fh_gmac_platform_data fh_gmac_data = {
+ .phy_reset_pin = 29,
+};
+
+static struct fh_uart_dma uart1_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART1_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART1_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART1_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART1_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+static struct fh_uart_dma uart2_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART2_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART2_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART2_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART2_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+
+static struct fh_platform_uart fh_uart_platform_data[] = {
+ {
+ .mapbase = UART0_REG_BASE,
+ .fifo_size = 16,
+ .irq = UART0_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = NULL,
+ },
+ {
+ .mapbase = UART1_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART1_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart1_dma_info,
+ },
+ {
+ .mapbase = UART2_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART2_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart2_dma_info,
+ },
+};
+
+static struct resource fh_pwm_resources[] = {
+ {
+ .start = PWM_REG_BASE,
+ .end = PWM_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PWM_IRQ,
+ .end = PWM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_i2c_resources_0[] = {
+ {
+ .start = I2C0_REG_BASE,
+ .end = I2C0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C0_IRQ,
+ .end = I2C0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_1[] = {
+ {
+ .start = I2C1_REG_BASE,
+ .end = I2C1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C1_IRQ,
+ .end = I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_2[] = {
+ {
+ .start = I2C2_REG_BASE,
+ .end = I2C2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C2_IRQ,
+ .end = I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_rtc_resources[] = {
+ {
+ .start = RTC_REG_BASE,
+ .end = RTC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio0_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO0",
+ .base = 0,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio1_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO1",
+ .base = 32,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_pwm_data pwm_data = {
+ .npwm = 12,
+};
+
+static struct resource fh_sadc_resources[] = {
+ {
+ .start = SADC_REG_BASE,
+ .end = SADC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SADC_IRQ,
+ .end = SADC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_aes_resources[] = {
+ {
+ .start = AES_REG_BASE,
+ .end = AES_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = AES_IRQ,
+ .end = AES_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_efuse_resources[] = {
+ {
+ .start = EFUSE_REG_BASE,
+ .end = EFUSE_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct resource fh_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+static struct resource fh_axi_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+static struct resource fh_spi0_resources[] = {
+ {
+ .start = SPI0_REG_BASE,
+ .end = SPI0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI0_IRQ,
+ .end = SPI0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi1_resources[] = {
+ {
+ .start = SPI1_REG_BASE,
+ .end = SPI1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI1_IRQ,
+ .end = SPI1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi2_resources[] = {
+ {
+ .start = SPI2_REG_BASE,
+ .end = SPI2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "fh spi2 mem",
+ },
+ {
+ .start = SPI2_IRQ,
+ .end = SPI2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ .name = "fh spi2 irq",
+ },
+};
+
+static struct resource fh_usb_resources[] = {
+ {
+ .start = USBC_REG_BASE,
+ .end = USBC_REG_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USBC_IRQ,
+ .end = USBC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static unsigned int fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+
+struct fh_mci_board fh_mci = {
+ .num_slots = 1,
+ .get_cd = fh_mci_sys_card_detect_fixed,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+ .rescan_max_num = 2,
+};
+
+struct fh_mci_board fh_mci_sd = {
+ .num_slots = 1,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+};
+
+static struct platform_device fh_gmac_device = {
+ .name = "fh_gmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gmac_resources),
+ .resource = fh_gmac_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_gmac_data,
+ },
+};
+
+struct platform_device fh_sd0_device = {
+ .name = "fh_mci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sdc0_resources),
+ .resource = fh_sdc0_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci_sd,
+ }
+};
+
+struct platform_device fh_sd1_device = {
+ .name = "fh_mci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_sdc1_resources),
+ .resource = fh_sdc1_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci,
+ }
+};
+
+struct fh_sadc_platform_data fh_sadc_data = {
+ .ref_vol = 1800,
+ .active_bit = 0xfff,
+};
+
+static struct platform_device fh_sadc_device = {
+ .name = "fh_sadc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sadc_resources),
+ .resource = fh_sadc_resources,
+ .dev = {
+ .platform_data = &fh_sadc_data,
+ },
+};
+
+static struct platform_device fh_uart0_device = {
+ .name = "ttyS",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_uart0_resources),
+ .resource = fh_uart0_resources,
+ .dev.platform_data = &fh_uart_platform_data[0],
+};
+
+static struct platform_device fh_uart1_device = {
+ .name = "ttyS",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_uart1_resources),
+ .resource = fh_uart1_resources,
+ .dev.platform_data = &fh_uart_platform_data[1],
+};
+
+static struct platform_device fh_uart2_device = {
+ .name = "ttyS",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_uart2_resources),
+ .resource = fh_uart2_resources,
+ .dev.platform_data = &fh_uart_platform_data[2],
+};
+
+static struct platform_device fh_pinctrl_device = {
+ .name = "fh_pinctrl",
+ .id = 0,
+};
+
+static struct platform_device fh_i2c0_device = {
+ .name = "fh_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_0),
+ .resource = fh_i2c_resources_0,
+};
+
+static struct platform_device fh_i2c1_device = {
+ .name = "fh_i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_1),
+ .resource = fh_i2c_resources_1,
+};
+
+static struct platform_device fh_i2c2_device = {
+ .name = "fh_i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_2),
+ .resource = fh_i2c_resources_2,
+};
+
+static struct fh_rtc_plat_data rtc_plat_data[] = {
+ {
+ .lut_cof = 58,
+ .lut_offset = 0xff,
+ .tsensor_cp_default_out = 0x993,
+ .clk_name = "rtc_hclk_gate",
+ },
+ {
+ .lut_cof = 71,
+ .lut_offset = 0xf6,
+ .tsensor_cp_default_out = 0x9cc,
+ .clk_name = "rtc_hclk_gate",
+ }
+};
+
+static struct platform_device fh_rtc_device = {
+ .name = "fh_rtc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_rtc_resources),
+ .resource = fh_rtc_resources,
+ .dev.platform_data = &rtc_plat_data[0],
+};
+
+static struct resource fh_i2s_resources[] = {
+ {
+ .start = I2S_REG_BASE,
+ .end = I2S_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ACW_REG_BASE,
+ .end = ACW_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = I2S0_IRQ,
+ .end = I2S0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_i2s_platform_data fh_i2s_data = {
+ .dma_capture_channel = 4,
+ .dma_playback_channel = 5,
+ .dma_master = 0,
+ .dma_rx_hs_num = 10,
+ .dma_tx_hs_num = 11,
+ .clk = "i2s_clk",
+ .acodec_mclk = "ac_clk",
+};
+
+static struct platform_device fh_i2s_device = {
+ .name = "fh_audio",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2s_resources),
+ .resource = fh_i2s_resources,
+ .dev = {
+ .platform_data = &fh_i2s_data,
+ },
+};
+
+static struct platform_device fh_gpio0_device = {
+ .name = GPIO_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gpio0_resources),
+ .resource = fh_gpio0_resources,
+ .dev = {
+ .platform_data = &fh_gpio0_chip,
+ },
+};
+
+static struct platform_device fh_gpio1_device = {
+ .name = GPIO_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_gpio1_resources),
+ .resource = fh_gpio1_resources,
+ .dev = {
+ .platform_data = &fh_gpio1_chip,
+ },
+};
+
+static struct platform_device fh_aes_device = {
+ .name = "fh_aes",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_aes_resources),
+ .resource = fh_aes_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+struct fh_efuse_platform_data fh_efuse_plat_data = {
+ .efuse_support_flag = CRYPTO_CPU_SET_KEY |
+ CRYPTO_EX_MEM_SET_KEY |
+ CRYPTO_EX_MEM_SWITCH_KEY |
+ CRYPTO_EX_MEM_4_ENTRY_1_KEY |
+ CRYPTO_EX_MEM_INDEP_POWER,
+};
+
+
+
+#define FH_SPI0_CS0 (6)
+#define FH_SPI0_CS1 (55)
+
+#define FH_SPI1_CS0 (14)
+#define FH_SPI1_CS1 (57)
+
+#define SPI0_FIFO_DEPTH (128)
+#define SPI0_CLK_IN (200000000)
+#define SPI0_MAX_SLAVE_NO (2)
+#define SPI0_DMA_RX_CHANNEL (0)
+#define SPI0_DMA_TX_CHANNEL (1)
+
+#define SPI1_FIFO_DEPTH (64)
+#define SPI1_CLK_IN (100000000)
+#define SPI1_MAX_SLAVE_NO (2)
+#define SPI1_DMA_RX_CHANNEL (2)
+#define SPI1_DMA_TX_CHANNEL (3)
+
+#define SPI2_CLK_IN (100000000)
+
+/* SPI_TRANSFER_USE_DMA */
+static struct fh_spi_platform_data fh_spi0_data = {
+ .bus_no = 0,
+ .apb_clock_in = SPI0_CLK_IN,
+ .clock_source = {100000000, 150000000, 200000000},
+ .clock_source_num = 3,
+ .slave_max_num = SPI0_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI0_CS0,
+ .cs_data[0].name = "spi0_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI0_CS1,
+ .cs_data[1].name = "spi0_cs1",
+ .clk_name = "spi0_clk",
+ .dma_transfer_enable = SPI_TRANSFER_USE_DMA,
+ .rx_dma_channel = SPI0_DMA_RX_CHANNEL,
+ .rx_handshake_num = 4,
+ /*dma use inc mode could move data by burst mode...*/
+ /*or move data use single mode with low efficient*/
+ .ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |
+ MULTI_WIRE_SUPPORT,
+};
+
+static struct fh_spi_platform_data fh_spi1_data = {
+ .bus_no = 1,
+ .apb_clock_in = SPI1_CLK_IN,
+ .clock_source = {SPI1_CLK_IN},
+ .clock_source_num = 1,
+ .slave_max_num = SPI1_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI1_CS0,
+ .cs_data[0].name = "spi1_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI1_CS1,
+ .cs_data[1].name = "spi1_cs1",
+ .clk_name = "spi1_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct fh_spi_platform_data fh_spi2_data = {
+ .apb_clock_in = SPI2_CLK_IN,
+ .dma_transfer_enable = 0,
+ .rx_handshake_num = 12,
+ .clk_name = "spi2_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct platform_device fh_efuse_device = {
+ .name = "fh_efuse",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_efuse_resources),
+ .resource = fh_efuse_resources,
+ .dev = {
+ .platform_data = &fh_efuse_plat_data,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct fh_dma_platform_data fh_dma_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .nr_channels = 6,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_dma_device = {
+ .name = "fh_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_dma_resources),
+ .resource = fh_dma_resources,
+ .dev = {
+ .platform_data = &fh_dma_data,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+struct fh_axi_dma_platform_data axi_dma_plat_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_axi_dma_device = {
+ .name = "fh_axi_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_axi_dma_resources),
+ .resource = fh_axi_dma_resources,
+ .dev = {
+ .platform_data = &axi_dma_plat_data,
+ },
+};
+#endif
+
+
+
+static struct platform_device fh_spi0_device = {
+ .name = "fh_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi0_resources),
+ .resource = fh_spi0_resources,
+ .dev = {
+ .platform_data = &fh_spi0_data,
+ },
+};
+
+static struct platform_device fh_spi1_device = {
+ .name = "fh_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_spi1_resources),
+ .resource = fh_spi1_resources,
+ .dev = {
+ .platform_data = &fh_spi1_data,
+ },
+};
+
+static struct platform_device fh_spi2_device = {
+ .name = "fh_spi_slave",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi2_resources),
+ .resource = fh_spi2_resources,
+ .dev = {
+ .platform_data = &fh_spi2_data,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct platform_device fh_perf_device = {
+ .name = "fh_perf_mon",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_perf_resources),
+ .resource = fh_perf_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+static struct fh_wdt_platform_data fh_wdt_data = {
+ .mode = MODE_DISCRETE,
+};
+
+struct platform_device fh_wdt_device = {
+ .name = "fh_wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_wdt_resources),
+ .resource = fh_wdt_resources,
+ .dev = {
+ .platform_data = &fh_wdt_data,
+ }
+};
+
+static struct platform_device fh_pwm_device = {
+ .name = "fh_pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_pwm_resources),
+ .resource = fh_pwm_resources,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
+};
+
+static struct fh_usb_platform_data fh_usb_data = {
+ .dr_mode = "host",
+ .vbus_pwren = 47,
+};
+
+struct platform_device fh_usb_device = {
+ .name = "fh_usb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_usb_resources),
+ .resource = fh_usb_resources,
+ .dev = {
+ .platform_data = &fh_usb_data,
+ }
+};
+
+#ifdef CONFIG_FH_TSENSOR
+struct platform_device fh_tsensor_device = {
+ .name = "fh_tsensor",
+ .id = 0,
+};
+#endif
+
+static struct platform_device *fh8852v210_devices[] __initdata = {
+ &fh_uart0_device,
+ &fh_uart1_device,
+ &fh_uart2_device,
+ &fh_pinctrl_device,
+ &fh_i2c0_device,
+ &fh_i2c1_device,
+ &fh_i2c2_device,
+ &fh_rtc_device,
+ &fh_sd0_device,
+ &fh_sd1_device,
+ &fh_sadc_device,
+ &fh_gmac_device,
+ &fh_gpio0_device,
+ &fh_gpio1_device,
+ &fh_aes_device,
+ &fh_efuse_device,
+#ifdef CONFIG_FH_DMAC
+ &fh_dma_device,
+#endif
+#ifdef CONFIG_FH_AXI_DMAC
+ &fh_axi_dma_device,
+#endif
+ &fh_spi0_device,
+ &fh_spi1_device,
+ &fh_spi2_device,
+ &fh_i2s_device,
+ &fh_pwm_device,
+ &fh_wdt_device,
+ &fh_usb_device,
+#ifdef CONFIG_FH_PERF_MON
+ &fh_perf_device,
+#endif
+#ifdef CONFIG_FH_TSENSOR
+ &fh_tsensor_device,
+#endif
+};
+
+static struct mtd_partition fh_sf_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* Ramboot & U-Boot environment */
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* U-Boot */
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi_flash:256k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),4M(kernel),
+ * 8M(rootfs),
+ * -(app) */
+ /* two blocks with bad block table (and mirror) at the end */
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct mtd_partition fh_sf_nand_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_512K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi0.0:64k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),
+ * 4M(kernel),
+ * 8M(rootfs),
+ * -(app)
+ * two blocks with bad block table (and mirror) at the end
+ */
+};
+#endif
+
+static struct flash_platform_data fh_flash_platform_data = {
+ .name = "spi_flash",
+ .parts = fh_sf_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_parts),
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct flash_platform_data fh_nandflash_platform_data = {
+ .name = "spi_nandflash",
+ .parts = fh_sf_nand_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_nand_parts),
+};
+#endif
+
+static struct spi_board_info fh_spi_devices[] = {
+#ifdef CONFIG_MTD_SPI_NAND
+ {
+ .modalias = "spi-nand",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &fh_nandflash_platform_data,
+ },
+#endif
+ {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ /* multi wire should adapt spi para 'ctl_wire_support'*/
+ .mode = SPI_MODE_3 | SPI_RX_DUAL,
+ .max_speed_hz = 50000000,
+ .platform_data = &fh_flash_platform_data,
+ },
+
+};
+
+extern void early_print(const char *str, ...);
+
+static void __init fh_console_pre_init(struct fh_platform_uart *plat, int num)
+{
+ int idx = 0;
+
+ for (; idx < num; idx++) {
+ struct uart_port *port;
+
+ port = &fh_serial_ports[idx];
+ port->mapbase = plat[idx].mapbase;
+ port->fifosize = plat[idx].fifo_size;
+ port->uartclk = plat[idx].uartclk;
+
+ switch (idx) {
+ case 0:
+ port->membase = (unsigned char *)VA_UART0_REG_BASE;
+ break;
+ case 1:
+ port->membase = (unsigned char *)VA_UART1_REG_BASE;
+ break;
+ case 2:
+ port->membase = (unsigned char *)VA_UART2_REG_BASE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void __init fh8852v210_map_io(void)
+{
+ iotable_init(fh8852v210_io_desc, ARRAY_SIZE(fh8852v210_io_desc));
+ fh_console_pre_init(fh_uart_platform_data,
+ ARRAY_SIZE(fh_uart_platform_data));
+}
+
+
+static __init void fh8852v210_board_init(void)
+{
+ if (fh_is_8852v210())
+ fh_rtc_device.dev.platform_data = &rtc_plat_data[1];
+ platform_add_devices(fh8852v210_devices,
+ ARRAY_SIZE(fh8852v210_devices));
+ spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices));
+}
+void __init fh_timer_init_no_of(unsigned int iovbase,
+ unsigned int irqno);
+
+static void __init fh8852v210_init_early(void)
+{
+ fh_pmu_init();
+ fh_pinctrl_init(VA_PMU_REG_BASE + 0x80);
+}
+
+static void __init fh_time_init(void)
+{
+ unsigned int vtimerbase = (unsigned int)ioremap(TIMER_REG_BASE, SZ_4K);
+
+ fh_clk_init();
+ fh_timer_init_no_of(vtimerbase, TMR0_IRQ);
+
+}
+
+void __init fh_intc_init_no_of(unsigned int iovbase);
+static void __init fh_intc_init(void)
+{
+ unsigned int vintcbase = (unsigned int)ioremap(INTC_REG_BASE, SZ_4K);
+
+ fh_intc_init_no_of(vintcbase);
+
+}
+
+static void fh8852v210_restart
+ (enum reboot_mode mode, const char *cmd)
+{
+ fh_pmu_restart();
+}
+
+
+MACHINE_START(FH8852V210, "FH8852V210")
+ .atag_offset = 0x100,
+ .map_io = fh8852v210_map_io,
+ .init_irq = fh_intc_init,
+ .init_time = fh_time_init,
+ .init_machine = fh8852v210_board_init,
+ .init_early = fh8852v210_init_early,
+ .restart = fh8852v210_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-fh/fh8852v210/board_config.fh8852v210.appboard b/arch/arm/mach-fh/fh8852v210/board_config.fh8852v210.appboard
new file mode 100644
index 00000000..02dae328
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v210/board_config.fh8852v210.appboard
@@ -0,0 +1,44 @@
+#ifndef BOARD_CONFIG_H_
+#define BOARD_CONFIG_H_
+
+/*
+ * GPIO0 -> IRCUT_ON
+ * GPIO1 -> IRCUT_OFF
+ * GPIO2 -> USB_PWREN
+ * GPIO11 -> EMAC PHY Reset
+ * GPIO12 -> CIS_CLK
+ * GPIO13 -> CIS_RSTN
+ * GPIO14 -> CIS_PDN
+ * GPIO19 -> SD1_PWREN/WIFI_REG_ON
+ * GPIO20 -> AK7755 Reset
+ * GPIO24 -> LED0
+ * GPIO25 -> LED1
+ * GPIO26 -> Reset Configs
+ * GPIO27 -> AK7755 PowerDown
+ * GPIO28 -> IR
+ * GPIO53 -> USB_PWREN/SD0_PWREN
+ * GPIO55 -> SD1 WIFI Interrupt
+ */
+
+#define CONFIG_SD_CD_FIXED
+
+#define CONFIG_ISP_CLK_RATE 171000000
+#define CONFIG_JPEG_CLK_RATE 171000000
+#define CONFIG_VEU_CLK_RATE 240000000
+
+#define USB_VBUS_PWR_GPIO (47)
+
+#define CONFIG_PINCTRL_SELECT \
+ "ETH", "I2C0", "PWM2", "PWM3", "PWM4", "PWM5", "PWM6", \
+ "PWM7", "PWM8", "PWM9", "SADC_XAIN0", "SADC_XAIN1", \
+ "SD0_NO_WP", "SENSOR_CLK", "SSI0_4BIT", "UART0", \
+ "UART1", "GPIO4", "GPIO13", "GPIO30", "GPIO31", \
+ "GPIO32", "GPIO43", "GPIO44", "GPIO47", \
+\
+ "GPIO11", "GPIO14", "GPIO15", "GPIO16", "GPIO24", \
+ "GPIO25", "GPIO45", "GPIO46", "GPIO48", "GPIO49", \
+ "GPIO50", "GPIO51", "GPIO52", "GPIO53", "GPIO54", \
+ "GPIO55", "GPIO56", "GPIO57", "GPIO58", "GPIO59", \
+ "GPIO60", "GPIO61", "GPIO62", "GPIO63"
+
+#endif /* BOARD_CONFIG_H_ */
diff --git a/arch/arm/mach-fh/fh8852v210/chip.c b/arch/arm/mach-fh/fh8852v210/chip.c
new file mode 100644
index 00000000..9bbb3c49
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v210/chip.c
@@ -0,0 +1,747 @@
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/clock.h>
+#include <mach/board_config.h>
+
+/*
+ * external oscillator
+ * fixed to 24M
+ */
+static struct fh_clk osc_clk = {
+ .name = "osc_clk",
+ .frequency = OSC_FREQUENCY,
+ .flag = CLOCK_FIXED,
+};
+
+/*
+ * phase-locked-loop device,
+ * generates a higher frequency clock
+ * from the external oscillator reference
+ *PLL_DDR
+ */
+
+static struct fh_clk pll_ddr_rclk = {
+ .name = "pll_ddr_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL0,
+ .en_reg_offset = REG_PMU_PLL0_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_CPU*/
+static struct fh_clk pll_cpu_pclk = {
+ .name = "pll_cpu_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+static struct fh_clk pll_cpu_rclk = {
+ .name = "pll_cpu_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_SYS*/
+static struct fh_clk pll_sys_pclk = {
+ .name = "pll_sys_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+
+static struct fh_clk pll_sys_rclk = {
+ .name = "pll_sys_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+static struct fh_clk pllsysp_div12_clk = {
+ .name = "pllsysp_div12_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk ddr_clk = {
+ .name = "ddr_clk",
+ .flag = CLOCK_NODIV,
+ .parent = {&pll_ddr_rclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8,
+};
+static struct fh_clk arm_clk = {
+ .name = "arm_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NOGATE|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1,
+};
+static struct fh_clk arc_clk = {
+ .name = "arc_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400000,
+};
+static struct fh_clk ahb_clk = {
+ .name = "ahb_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&osc_clk, &pll_sys_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf0000,
+};
+
+static struct fh_clk isp_aclk = {
+ .name = "isp_aclk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1,
+ .def_rate = CONFIG_ISP_CLK_RATE,
+};
+static struct fh_clk ispb_aclk = {
+ .name = "ispb_aclk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4,
+};
+
+static struct fh_clk vpu_clk = {
+ .name = "vpu_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80000000,
+};
+
+static struct fh_clk pix_clk = {
+ .name = "pix_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk jpeg_clk = {
+ .name = "jpeg_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x40000000,
+ .def_rate = CONFIG_JPEG_CLK_RATE,
+};
+
+static struct fh_clk bgm_clk = {
+ .name = "bgm_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x40000,
+};
+
+static struct fh_clk jpeg_adapt_clk = {
+ .name = "jpeg_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&jpeg_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2,
+};
+static struct fh_clk spi0_clk = {
+ .name = "spi0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100,
+};
+static struct fh_clk sdc0_clk = {
+ .name = "sdc0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x4,
+};
+static struct fh_clk spi2_clk = {
+ .name = "spi2_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100000,
+};
+static struct fh_clk spi1_clk = {
+ .name = "spi1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x200,
+};
+static struct fh_clk sdc1_clk = {
+ .name = "sdc1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x2,
+};
+
+static struct fh_clk veu_clk = {
+ .name = "veu_clk",
+ .flag = CLOCK_MULTI_PARENT,
+ .parent = {&pll_sys_pclk, &pll_sys_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x4,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0x7000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000000,
+ .def_rate = CONFIG_VEU_CLK_RATE,
+
+};
+
+static struct fh_clk veu_adapt_clk = {
+ .name = "veu_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&veu_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000000,
+
+};
+
+static struct fh_clk cis_clk_out = {
+ .name = "cis_clk_out",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800000,
+};
+
+static struct fh_clk eth_clk = {
+ .name = "eth_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x12000000,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x20000,
+};
+static struct fh_clk i2c0_clk = {
+ .name = "i2c0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400,
+};
+
+static struct fh_clk i2c1_clk = {
+ .name = "i2c1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800,
+};
+
+static struct fh_clk i2c2_clk = {
+ .name = "i2c2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x00003f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x00000008,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20000000,
+};
+
+static struct fh_clk pwm_clk = {
+ .name = "pwm_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x80,
+ .def_rate = 50000000,
+};
+
+static struct fh_clk uart0_clk = {
+ .name = "uart0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x4000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk uart1_clk = {
+ .name = "uart1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000,
+ .def_rate = 16666666,
+};
+static struct fh_clk uart2_clk = {
+ .name = "uart2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = 0,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x7f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk efuse_clk = {
+ .name = "efuse_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800000,
+};
+
+static struct fh_clk pts_clk = {
+ .name = "pts_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = CLOCK_NORESET,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0x1ff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL2,
+ .rst_reg_mask = 0x1,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk tmr0_clk = {
+ .name = "tmr0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x40000,
+};
+
+static struct fh_clk sadc_clk = {
+ .name = "sadc_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x7f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10000,
+};
+
+static struct fh_clk ac_clk = {
+ .name = "ac_clk",
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1000,
+};
+
+static struct fh_clk i2s_clk = {
+ .name = "i2s_clk",
+ .parent = {&ac_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000,
+};
+
+static struct fh_clk wdt_clk = {
+ .name = "wdt_clk",
+ .flag = 0,
+ .parent = {&ahb_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff00,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_APB_CTRL,
+ .rst_reg_mask = 0x100000,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk gpio0_db_clk = {
+ .name = "gpio0_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio1_db_clk = {
+ .name = "gpio1_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff0000,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x80000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20,
+};
+
+
+static struct fh_clk mipi_dphy_clk = {
+ .name = "mipi_dphy_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100000,
+};
+static struct fh_clk mipi_wrap_gate = {
+ .name = "mipi_wrap_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk rtc_hclk_gate = {
+ .name = "rtc_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk emac_hclk_gate = {
+ .name = "emac_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk usb_clk = {
+ .name = "usb_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk aes_hclk_gate = {
+ .name = "aes_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80,
+};
+static struct fh_clk ephy_clk_gate = {
+ .name = "ephy_clk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1,
+};
+static struct fh_clk sdc0_clk8x_gate = {
+ .name = "sdc0_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4,
+};
+static struct fh_clk sdc1_clk8x_gate = {
+ .name = "sdc1_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8,
+};
+static struct fh_clk mipic_pclk_gate = {
+ .name = "mipic_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio0_pclk_gate = {
+ .name = "gpio0_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x4000,
+};
+static struct fh_clk gpio1_pclk_gate = {
+ .name = "gpio1_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x40000000,
+};
+static struct fh_clk isp_hclk_gate = {
+ .name = "isp_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk veu_hclk_gate = {
+ .name = "veu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk bgm_hclk_gate = {
+ .name = "bgm_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x4000000,
+};
+static struct fh_clk adapt_hclk_gate = {
+ .name = "adapt_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x8000000,
+};
+static struct fh_clk jpg_hclk_gate = {
+ .name = "jpg_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk jpg_adapt_gate = {
+ .name = "jpg_adapt_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk vpu_hclk_gate = {
+ .name = "vpu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x40000000,
+};
+
+static struct fh_clk sdc0_clk_sample = {
+ .name = "sdc0_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf0000,
+};
+
+static struct fh_clk sdc0_clk_drv = {
+ .name = "sdc0_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00000,
+};
+
+static struct fh_clk sdc1_clk_sample = {
+ .name = "sdc1_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00,
+};
+
+static struct fh_clk sdc1_clk_drv = {
+ .name = "sdc1_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf000,
+};
+
+struct fh_clk *fh_clks[] = {
+ &osc_clk,
+ &pll_ddr_rclk,
+ &pll_cpu_pclk,
+ &pll_cpu_rclk,
+ &pll_sys_pclk,
+ &pll_sys_rclk,
+ &arm_clk,
+ &arc_clk,
+ &ahb_clk,
+ &ddr_clk,
+ &isp_aclk,
+ &ispb_aclk,
+ &jpeg_clk,
+ &jpeg_adapt_clk,
+ &vpu_clk,
+ &veu_clk,
+ &veu_adapt_clk,
+ &bgm_clk,
+ &mipi_dphy_clk,
+ &pllsysp_div12_clk,
+ &cis_clk_out,
+ &pix_clk,
+ &pts_clk,
+ &spi0_clk,
+ &spi1_clk,
+ &spi2_clk,
+ &sdc0_clk,
+ &sdc1_clk,
+ &uart0_clk,
+ &uart1_clk,
+ &uart2_clk,
+ &i2c0_clk,
+ &i2c1_clk,
+ &i2c2_clk,
+ &pwm_clk,
+ &wdt_clk,
+ &tmr0_clk,
+ &ac_clk,
+ &i2s_clk,
+ &sadc_clk,
+ &eth_clk,
+ &efuse_clk,
+ &gpio0_db_clk,
+ &gpio1_db_clk,
+ &mipi_wrap_gate,
+ &rtc_hclk_gate,
+ &emac_hclk_gate,
+ &usb_clk,
+ &aes_hclk_gate,
+ &ephy_clk_gate,
+ &sdc0_clk8x_gate,
+ &sdc1_clk8x_gate,
+ &gpio0_pclk_gate,
+ &gpio1_pclk_gate,
+ &mipic_pclk_gate,
+ &sdc0_clk_sample,
+ &sdc0_clk_drv,
+ &sdc1_clk_sample,
+ &sdc1_clk_drv,
+ &isp_hclk_gate,
+ &veu_hclk_gate,
+ &bgm_hclk_gate,
+ &adapt_hclk_gate,
+ &jpg_hclk_gate,
+ &jpg_adapt_gate,
+ &vpu_hclk_gate,
+ NULL,
+};
+EXPORT_SYMBOL(fh_clks);
diff --git a/arch/arm/mach-fh/fh8852v210/chip.h b/arch/arm/mach-fh/fh8852v210/chip.h
new file mode 100644
index 00000000..f2b2fcae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v210/chip.h
@@ -0,0 +1,420 @@
+#ifndef __ASM_ARCH_HL_H
+#define __ASM_ARCH_HL_H
+
+#include <linux/init.h>
+
+#define SRAM_GRANULARITY 32
+#define SRAM_SIZE (SZ_128K+SZ_8K)
+
+
+#define RAM_BASE (0x10000000)
+#define DDR_BASE (0xA0000000)
+
+
+#define PMU_REG_BASE (0xF0000000)
+#define TIMER_REG_BASE (0xF0C00000)
+#define GPIO0_REG_BASE (0xF0300000)
+#define GPIO1_REG_BASE (0xF4000000)
+#define UART0_REG_BASE (0xF0700000)
+#define UART1_REG_BASE (0xF0800000)
+#define SPI0_REG_BASE (0xF0500000)
+#define SPI1_REG_BASE (0xF0600000)
+#define SPI2_REG_BASE (0xF0640000)
+#define INTC_REG_BASE (0xE0200000)
+#define GMAC_REG_BASE (0xE0600000)
+#define USBC_REG_BASE (0xE0700000)
+#define DMAC_REG_BASE (0xE0300000)
+#define I2C1_REG_BASE (0xF0B00000)
+#define I2C0_REG_BASE (0xF0200000)
+#define I2C2_REG_BASE (0xF0100000)
+#define SDC0_REG_BASE (0xE2000000)
+#define SDC1_REG_BASE (0xE2200000)
+#define WDT_REG_BASE (0xF0D00000)
+#define PWM_REG_BASE (0xF0400000)
+#define I2S_REG_BASE (0xF0900000)
+#define ACW_REG_BASE (0xF0A00000)
+#define UART2_REG_BASE (0xF1300000)
+#define SADC_REG_BASE (0xF1200000)
+#define EFUSE_REG_BASE (0xF1600000)
+#define AES_REG_BASE (0xE8200000)
+#define RTC_REG_BASE (0xF1500000)
+#define DDRC_REG_BASE (0xED000000)
+#define CONSOLE_REG_BASE UART0_REG_BASE
+#define FH_UART_NUMBER 3
+
+#define FH_PMU_REG_SIZE 0x2110
+#define REG_PMU_CHIP_ID (0x0000)
+#define REG_PMU_IP_VER (0x0004)
+#define REG_PMU_FW_VER (0x0008)
+#define REG_PMU_CLK_SEL (0x000c)
+/*for HL REG_PMU_SYS_CTRL and CLK_SEL use one register */
+#define REG_PMU_SYS_CTRL (0x000c)
+#define REG_PMU_PLL0 (0x0010)
+#define REG_PMU_PLL1 (0x0014)
+#define REG_PMU_PLL0_CTRL (0x0018)
+#define REG_PMU_CLK_GATE (0x001c)
+#define REG_PMU_CLK_GATE1 (0x0020)
+#define REG_PMU_CLK_DIV0 (0x0024)
+#define REG_PMU_CLK_DIV1 (0x0028)
+#define REG_PMU_CLK_DIV2 (0x002c)
+#define REG_PMU_CLK_DIV3 (0x0030)
+#define REG_PMU_CLK_DIV4 (0x0034)
+#define REG_PMU_CLK_DIV5 (0x0038)
+#define REG_PMU_CLK_DIV6 (0x003c)
+#define REG_PMU_SWRST_MAIN_CTRL (0x0040)
+#define REG_PMU_SWRST_MAIN_CTRL2 (0x0044)
+#define REG_PMU_SWRST_AHB_CTRL (0x0048)
+#define REG_PMU_SWRST_APB_CTRL (0x004c)
+#define REG_PMU_SPC_IO_STATUS (0x0054)
+#define REG_PMU_SPC_FUN (0x0058)
+#define REG_PMU_CLK_DIV7 (0x005c)
+#define REG_PMU_CLK_DIV8 (0x0060)
+#define REG_PMU_PLL2 (0x0064)
+#define REG_PMU_PLL2_CTRL (0x0068)
+#define REG_PMU_PLL1_CTRL (0x006c)
+#define REG_PAD_PWR_SEL (0x0074)
+#define REG_PMU_SWRSTN_NSR (0x0078)
+#define REG_PMU_SWRSTN_NSR1 (0x007c)
+#define REG_PMU_ETHPHY_REG0 (0x2108)
+
+
+#define REG_PMU_PAD_BOOT_MODE_CFG (0x0080)
+#define REG_PMU_PAD_BOOT_SEL1_CFG (0x0084)
+#define REG_PMU_PAD_BOOT_SEL0_CFG (0x0088)
+#define REG_PMU_PAD_UART0_TX_CFG (0x008c)
+#define REG_PMU_PAD_UART0_RX_CFG (0x0090)
+#define REG_PMU_PAD_I2C0_SCL_CFG (0x0094)
+#define REG_PMU_PAD_I2C0_SDA_CFG (0x0098)
+#define REG_PMU_PAD_SENSOR_CLK_CFG (0x009c)
+#define REG_PMU_PAD_SENSOR_RSTN_CFG (0x00a0)
+#define REG_PMU_PAD_UART1_TX_CFG (0x00a4)
+#define REG_PMU_PAD_UART1_RX_CFG (0x00a8)
+#define REG_PMU_PAD_I2C1_SCL_CFG (0x00ac)
+#define REG_PMU_PAD_I2C1_SDA_CFG (0x00b0)
+#define REG_PMU_PAD_UART2_TX_CFG (0x00b4)
+#define REG_PMU_PAD_UART2_RX_CFG (0x00b8)
+#define REG_PMU_PAD_USB_PWREN_CFG (0x00bc)
+#define REG_PMU_PAD_PWM0_CFG (0x00c0)
+#define REG_PMU_PAD_PWM1_CFG (0x00c4)
+#define REG_PMU_PAD_PWM2_CFG (0x00c8)
+#define REG_PMU_PAD_PWM3_CFG (0x00cc)
+#define REG_PMU_PAD_MAC_RMII_CLK_CFG (0x00d0)
+#define REG_PMU_PAD_MAC_REF_CLK_CFG (0x00d4)
+#define REG_PMU_PAD_MAC_TXD0_CFG (0x00d8)
+#define REG_PMU_PAD_MAC_TXD1_CFG (0x00dc)
+#define REG_PMU_PAD_MAC_TXEN_CFG (0x00e0)
+#define REG_PMU_PAD_MAC_RXD0_CFG (0x00e4)
+#define REG_PMU_PAD_MAC_RXD1_CFG (0x00e8)
+#define REG_PMU_PAD_MAC_RXDV_CFG (0x00ec)
+#define REG_PMU_PAD_MAC_MDC_CFG (0x00f0)
+#define REG_PMU_PAD_MAC_MDIO_CFG (0x00f4)
+#define REG_PMU_PAD_SD1_CLK_CFG (0x00f8)
+#define REG_PMU_PAD_SD1_CD_CFG (0x00fc)
+#define REG_PMU_PAD_SD1_CMD_RSP_CFG (0x0100)
+#define REG_PMU_PAD_SD1_DATA_0_CFG (0x0104)
+#define REG_PMU_PAD_SD1_DATA_1_CFG (0x0108)
+#define REG_PMU_PAD_SD1_DATA_2_CFG (0x010c)
+#define REG_PMU_PAD_SD1_DATA_3_CFG (0x0110)
+#define REG_PMU_PAD_GPIO_0_CFG (0x0114)
+#define REG_PMU_PAD_GPIO_1_CFG (0x0118)
+#define REG_PMU_PAD_GPIO_2_CFG (0x011c)
+#define REG_PMU_PAD_GPIO_3_CFG (0x0120)
+#define REG_PMU_PAD_GPIO_4_CFG (0x0124)
+#define REG_PMU_PAD_SSI0_CLK_CFG (0x0128)
+#define REG_PMU_PAD_SSI0_CSN_0_CFG (0x012c)
+#define REG_PMU_PAD_SSI0_TXD_CFG (0x0130)
+#define REG_PMU_PAD_SSI0_RXD_CFG (0x0134)
+#define REG_PMU_PAD_SSI0_D2_CFG (0x0138)
+#define REG_PMU_PAD_SSI0_D3_CFG (0x013c)
+#define REG_PMU_PAD_SSI1_CLK_CFG (0x0140)
+#define REG_PMU_PAD_SSI1_CSN_0_CFG (0x0144)
+#define REG_PMU_PAD_SSI1_TXD_CFG (0x0148)
+#define REG_PMU_PAD_SSI1_RXD_CFG (0x014c)
+#define REG_PMU_PAD_SD0_CD_CFG (0x0150)
+#define REG_PMU_PAD_SD0_CLK_CFG (0x0154)
+#define REG_PMU_PAD_SD0_CMD_RSP_CFG (0x0158)
+#define REG_PMU_PAD_SD0_DATA_0_CFG (0x015c)
+#define REG_PMU_PAD_SD0_DATA_1_CFG (0x0160)
+#define REG_PMU_PAD_SD0_DATA_2_CFG (0x0164)
+#define REG_PMU_PAD_SD0_DATA_3_CFG (0x0168)
+#define REG_PMU_PAD_SADC_XAIN0_CFG (0x016c)
+#define REG_PMU_PAD_SADC_XAIN1_CFG (0x0170)
+#define REG_PMU_PAD_SADC_XAIN2_CFG (0x0174)
+#define REG_PMU_PAD_SADC_XAIN3_CFG (0x0178)
+#define REG_PMU_PAD_GPIO_28_CFG (0x017c)
+#define REG_PMU_PAD_GPIO_29_CFG (0x0180)
+
+#define REG_PMU_ARM_INT_0 (0x01e0)
+#define REG_PMU_ARM_INT_1 (0x01e4)
+#define REG_PMU_ARM_INT_2 (0x01e8)
+#define REG_PMU_A625_INT_0 (0x01ec)
+#define REG_PMU_A625_INT_1 (0x01f0)
+#define REG_PMU_A625_INT_2 (0x01f4)
+#define REG_PMU_DMA (0x01f8)
+#define REG_PMU_WDT_CTRL (0x01fc)
+#define REG_PMU_DBG_STAT0 (0x0200)
+#define REG_PMU_DBG_STAT1 (0x0204)
+#define REG_PMU_DBG_STAT2 (0x0208)
+#define REG_PMU_DBG_STAT3 (0x020c)
+#define REG_PMU_USB_SYS (0x0210)
+#define REG_PMU_USB_CFG (0x0214)
+#define REG_PMU_USB_TUNE (0x0218)
+#define REG_PMU_USB_SYS1 (0x0228)
+#define REG_PMU_PTSLO (0x022c)
+#define REG_PMU_PTSHI (0x0230)
+#define REG_PMU_USER0 (0x0234)
+#define REG_PMU_BOOT_MODE (0x0330)
+#define REG_PMU_DDR_SIZE (0x0334)
+#define REG_PMU_CHIP_INFO (0x033C)
+#define REG_PMU_EPHY_PARAM (0x0340)
+#define REG_PMU_RTC_PARAM (0x0344)
+#define REG_PMU_SD1_FUNC_SEL (0x03a0)
+#define REG_PMU_PRDCID_CTRL0 (0x0500)
+#define REG_PMU_A625BOOT0 (0x2000)
+#define REG_PMU_A625BOOT1 (0x2004)
+#define REG_PMU_A625BOOT2 (0x2008)
+#define REG_PMU_A625BOOT3 (0x200c)
+#define REG_PMU_A625_START_CTRL (0x2010)
+#define REG_PMU_ARC_INTC_MASK (0x2014)
+
+#define FH_GMAC_AHB_RESET (1<<17)
+#define FH_GMAC_SPEED_100M (1<<24)
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+#define PMU_RXDV_GPIO_SWITCH (REG_PMU_PAD_MAC_RXDV_CFG)
+#define PMU_RXDV_GPIO_MASK (0x0f000000)
+#define PMU_RXDV_GPIO_VAL (0x01000000)
+
+#define PMU_DWI2S_CLK_SEL_REG (REG_PMU_CLK_SEL)
+#define PMU_DWI2S_CLK_SEL_SHIFT (1)
+#define PMU_DWI2S_CLK_DIV_REG (REG_PMU_CLK_DIV6)
+#define PMU_DWI2S_CLK_DIV_SHIFT (0)
+
+/*ATTENTION: written by ARC */
+#define PMU_ARM_INT_MASK (0x01ec)
+#define PMU_ARM_INT_RAWSTAT (0x01f0)
+#define PMU_ARM_INT_STAT (0x01f4)
+
+#define PMU_A625_INT_MASK (0x01e0)
+#define PMU_A625_INT_RAWSTAT (0x01e4)
+#define PMU_A625_INT_STAT (0x01e8)
+
+#define PMU_IRQ 0
+#define DDRC_IRQ 1
+#define WDT_IRQ 2
+#define TMR0_IRQ 3
+#define VEU_IRQ 4
+#define PERF_IRQ 5
+#define VPU_IRQ 9
+#define I2C0_IRQ 11
+#define I2C1_IRQ 12
+#define JPEG_IRQ 13
+#define BGM_IRQ 14
+#define VEU_LOOP_IRQ 15
+#define AES_IRQ 16
+#define MIPIC_IRQ 17
+#define MIPI_WRAP_IRQ 18
+#define ACW_IRQ 19
+#define SADC_IRQ 20
+#define SPI1_IRQ 21
+#define JPEG_LOOP_IRQ 22
+#define DMAC0_IRQ 23
+#define DMAC1_IRQ 24
+#define I2S0_IRQ 25
+#define GPIO0_IRQ 26
+#define SPI0_IRQ 28
+#define ARC_SW_IRQ 29
+#define UART0_IRQ 30
+#define UART1_IRQ 31
+#define ARM_SW_IRQ 32
+#define RTC_IRQ 33
+#define PWM_IRQ 36
+#define SPI2_IRQ 38
+#define USBC_IRQ 39
+#define GPIO1_IRQ 40
+#define UART2_IRQ 41
+#define SDC0_IRQ 42
+#define SDC1_IRQ 43
+#define GMAC_IRQ 44
+#define EPHY_IRQ 45
+#define I2C2_IRQ 46
+#define RTC_ALM_IRQ 47
+#define RTC_CORE_IRQ 48
+/* because chips with some same function in different */
+/* pmu register, use wrap marco to make code to be same */
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+
+#define MEM_START_PHY_ADDR DDR_BASE
+#define MEM_SIZE 0x4000000
+
+
+#define NR_INTERNAL_IRQS (64)
+#define NR_EXTERNAL_IRQS (64)
+/*#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS)*/
+
+/* SWRST_MAIN_CTRL */
+#define CPU_RSTN_BIT (0)
+#define UTMI_RSTN_BIT (1)
+#define DDRPHY_RSTN_BIT (2)
+#define DDRC_RSTN_BIT (3)
+#define GPIO0_DB_RSTN_BIT (4)
+#define GPIO1_DB_RSTN_BIT (5)
+#define PIXEL_RSTN_BIT (6)
+#define PWM_RSTN_BIT (7)
+#define SPI0_RSTN_BIT (8)
+#define SPI1_RSTN_BIT (9)
+#define I2C0_RSTN_BIT (10)
+#define I2C1_RSTN_BIT (11)
+#define ACODEC_RSTN_BIT (12)
+#define I2S_RSTN_BIT (13)
+#define UART0_RSTN_BIT (14)
+#define UART1_RSTN_BIT (15)
+#define SADC_RSTN_BIT (16)
+#define ADAPT_RSTN_BIT (17)
+#define TMR_RSTN_BIT (18)
+#define UART2_RSTN_BIT (19)
+#define SPI2_RSTN_BIT (20)
+#define JPG_ADAPT_RSTN_BIT (21)
+#define ARC_RSTN_BIT (22)
+#define EFUSE_RSTN_BIT (23)
+#define JPG_RSTN_BIT (24)
+#define VEU_RSTN_BIT (25)
+#define VPU_RSTN_BIT (26)
+#define ISP_RSTN_BIT (27)
+#define BGM_RSTN_BIT (28)
+#define I2C2_RSTN_BIT (29)
+#define EPHY_RSTN_BIT (30)
+#define SYS_RSTN_BIT (31)
+
+/* SWRST_AHB_CTRL */
+#define EMC_HRSTN_BIT (0)
+#define SDC1_HRSTN_BIT (1)
+#define SDC0_HRSTN_BIT (2)
+#define AES_HRSTN_BIT (3)
+#define DMAC0_HRSTN_BIT (4)
+#define INTC_HRSTN_BIT (5)
+#define JPEG_ADAPT_HRSTN_BIT (7)
+#define JPEG_HRSTN_BIT (8)
+#define VCU_HRSTN_BIT (9)
+#define VPU_HRSTN_BIT (10)
+#define ISP_HRSTN_BIT (11)
+#define USB_HRSTN_BIT (12)
+#define HRSTN_BIT (13)
+#define EMAC_HRSTN_BIT (17)
+#define DDRC_HRSTN_BIT (19)
+#define DMAC1_HRSTN_BIT (20)
+#define BGM_HRSTN_BIT (22)
+#define ADAPT_HRSTN_BIT (23)
+
+/* SWRST_APB_CTRL */
+#define ACODEC_PRSTN_BIT (0)
+#define I2S_PRSTN_BIT (1)
+#define UART1_PRSTN_BIT (2)
+#define UART0_PRSTN_BIT (3)
+#define SPI0_PRSTN_BIT (4)
+#define SPI1_PRSTN_BIT (5)
+#define GPIO0_PRSTN_BIT (6)
+#define UART2_PRSTN_BIT (7)
+#define I2C2_PRSTN_BIT (8)
+#define I2C0_PRSTN_BIT (9)
+#define I2C1_PRSTN_BIT (10)
+#define TMR_PRSTN_BIT (11)
+#define PWM_PRSTN_BIT (12)
+#define MIPIW_PRSTN_BIT (13)
+#define MIPIC_PRSTN_BIT (14)
+#define RTC_PRSTN_BIT (15)
+#define SADC_PRSTN_BIT (16)
+#define EFUSE_PRSTN_BIT (17)
+#define SPI2_PRSTN_BIT (18)
+#define WDT_PRSTN_BIT (19)
+#define GPIO1_PRSTN_BIT (20)
+
+/* timer clk fpga 1M,soc 50M*/
+#ifdef CONFIG_FPGA
+#define TIMER_CLK (1000000)
+#else
+#define TIMER_CLK (50000000)
+#endif
+
+#define UART1_TX_HW_HANDSHAKE (9)
+#define UART1_RX_HW_HANDSHAKE (8)
+#define UART2_TX_HW_HANDSHAKE (13)
+#define UART2_RX_HW_HANDSHAKE (12)
+#define UART1_DMA_TX_CHAN (4)
+#define UART1_DMA_RX_CHAN (5)
+#define UART2_DMA_TX_CHAN (4)
+#define UART2_DMA_RX_CHAN (5)
+
+/*sdio*/
+#define SIMPLE_0 (0)
+#define SIMPLE_22 (1)
+#define SIMPLE_45 (2)
+#define SIMPLE_67 (3)
+#define SIMPLE_90 (4)
+#define SIMPLE_112 (5)
+#define SIMPLE_135 (6)
+#define SIMPLE_157 (7)
+#define SIMPLE_180 (8)
+#define SIMPLE_202 (9)
+#define SIMPLE_225 (10)
+#define SIMPLE_247 (11)
+#define SIMPLE_270 (12)
+#define SIMPLE_292 (13)
+#define SIMPLE_315 (14)
+#define SIMPLE_337 (15)
+
+
+
+#define SDIO0_RST_BIT (~UL(1<<2))
+#define SDIO0_CLK_RATE (50000000)
+#define SDIO0_CLK_DRV_SHIFT (20)
+#define SDIO0_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO0_CLK_SAM_SHIFT (16)
+#define SDIO0_CLK_SAM_DEGREE (SIMPLE_0)
+
+
+#define SDIO1_RST_BIT (~UL(1<<1))
+#define SDIO1_CLK_RATE (50000000)
+#define SDIO1_CLK_DRV_SHIFT (12)
+#define SDIO1_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO1_CLK_SAM_SHIFT (8)
+#define SDIO1_CLK_SAM_DEGREE (SIMPLE_0)
+
+#define SDC0_HRSTN (0x1<<2)
+#define SDC1_HRSTN (0x1<<1)
+#define SDC2_HRSTN (0)
+
+
+/*usb*/
+#define IRQ_UHOST USBC_IRQ
+#define FH_PA_OTG USBC_REG_BASE
+#define IRQ_OTG IRQ_UHOST
+#define FH_SZ_USBHOST SZ_1M
+#define FH_SZ_OTG SZ_1M
+
+#define USB_UTMI_RST_BIT (0x1<<1)
+#define USB_PHY_RST_BIT (0x11)
+#define USB_SLEEP_MODE_BIT (0x1<<24)
+#define USB_IDDQ_PWR_BIT (0x1<<10)
+
+
+/* Specific Uart Number */
+#define FH_UART_NUMBER 3
+#define CLK_SCAN_BIT_POS (28)
+#define INSIDE_PHY_ENABLE_BIT_POS (24)
+#define MAC_REF_CLK_DIV_MASK (0x0f)
+#define MAC_REF_CLK_DIV_BIT_POS (24)
+#define MAC_PAD_RMII_CLK_MASK (0x0f)
+#define MAC_PAD_RMII_CLK_BIT_POS (24)
+#define MAC_PAD_MAC_REF_CLK_BIT_POS (28)
+#define ETH_REF_CLK_OUT_GATE_BIT_POS (25)
+#define ETH_RMII_CLK_OUT_GATE_BIT_POS (28)
+#define IN_OR_OUT_PHY_SEL_BIT_POS (26)
+#define INSIDE_CLK_GATE_BIT_POS (0)
+#define INSIDE_PHY_SHUTDOWN_BIT_POS (31)
+#define INSIDE_PHY_RST_BIT_POS (30)
+#define INSIDE_PHY_TRAINING_BIT_POS (27)
+#define INSIDE_PHY_TRAINING_MASK (0x0f)
+
+#define TRAINING_EFUSE_ACTIVE_BIT_POS 4
+
+#endif /* __ASM_ARCH_HL_H */
diff --git a/arch/arm/mach-fh/fh8852v210/iopad.h b/arch/arm/mach-fh/fh8852v210/iopad.h
new file mode 100644
index 00000000..ebc24024
--- /dev/null
+++ b/arch/arm/mach-fh/fh8852v210/iopad.h
@@ -0,0 +1,729 @@
+#include <mach/pinctrl.h>
+#include <mach/pinctrl_osdep.h>
+#include <mach/board_config.h>
+
+/* PINCTRL_FUNC */
+PINCTRL_FUNC(GPIO30, 0, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO31, 1, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 1, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO32, 2, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 2, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 2, FUNC2, PUPD_UP, 0);
+PINCTRL_FUNC(UART0_TX, 3, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO33, 3, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART0_RX, 4, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO34, 4, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C0_SCL, 5, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO35, 5, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(I2C0_SDA, 6, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO36, 6, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(SENSOR_CLK, 7, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO12, 7, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO13, 8, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 9, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO39, 9, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 9, FUNC3, PUPD_NONE, 3);
+PINCTRL_FUNC(TEST_O_INT_RMII_CLK, 9, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 10, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO40, 10, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 10, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_0, 10, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 11, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO37, 11, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 11, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 11, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 11, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_1, 11, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 12, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO38, 12, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 12, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 12, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 12, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXEN, 12, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 13, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO41, 13, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM4, 13, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 13, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 13, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_0, 13, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 14, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO42, 14, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM5, 14, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 14, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 14, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_1, 14, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 15, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO47, 15, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 15, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_CRSDV, 15, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM0, 16, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO43, 16, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SCL, 16, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 16, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_0, 16, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM1, 17, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO44, 17, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SDA, 17, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 17, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_1, 17, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 18, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO45, 18, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 19, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO46, 19, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RMII_CLK, 20, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO48, 20, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 20, FUNC2, PUPD_NONE, 3);
+PINCTRL_FUNC(PWM2, 20, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_REF_CLK, 21, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(MAC_TXD_0, 22, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO49, 22, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 22, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM3, 22, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXD_1, 23, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO50, 23, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 23, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM4, 23, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXEN, 24, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO51, 24, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 24, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM5, 24, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_0, 25, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO52, 25, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 25, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM6, 25, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_1, 26, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO53, 26, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 26, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM7, 26, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXDV, 27, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO54, 27, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 27, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM8, 27, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 28, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO55, 28, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 28, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 29, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO56, 29, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 30, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO57, 30, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 30, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 31, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO58, 31, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 31, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO59, 32, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 32, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 33, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO60, 33, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 33, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 34, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO61, 34, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 34, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 35, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO62, 35, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 35, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 36, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO63, 36, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TRSTN, 37, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO0, 37, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DO, 37, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DO, 37, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CLK, 37, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CLK, 37, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADDAT, 37, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM6, 37, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDC, 37, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDO, 38, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO1, 38, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DI, 38, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DI, 38, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CSN_0, 38, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DADAT, 38, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM7, 38, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_I, 38, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDI, 39, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO2, 39, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_CLK, 39, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_CLK, 39, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_TXD, 39, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_TXD, 39, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADBCLK, 39, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM8, 39, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_O, 39, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TCK, 40, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO3, 40, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_WS, 40, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_WS, 40, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_RXD, 40, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_RXD, 40, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADLRC, 40, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 40, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDIO_I, 40, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TMS, 41, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO4, 41, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_MCLK, 41, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 41, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 41, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDC, 41, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI0_CLK, 42, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO5, 42, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CLK, 42, FUNC4, PUPD_NONE, 3);
+PINCTRL_FUNC(SSI0_CSN_0, 43, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO6, 43, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CMD_RSP, 43, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_TXD, 44, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO7, 44, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_0, 44, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_RXD, 45, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO8, 45, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_1, 45, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D2, 46, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO9, 46, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_TX, 46, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SCL, 46, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_2, 46, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D3, 47, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO10, 47, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_RX, 47, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SDA, 47, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_3, 47, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 48, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO11, 48, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CLK, 48, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 49, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CSN_0, 49, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 50, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO15, 50, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_TXD, 50, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 51, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO16, 51, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_RXD, 51, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CD, 52, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO17, 52, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARC_JTAG_TRSTN, 52, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(PAE_JTAG_TRSTN, 52, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD0_CLK, 53, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO18, 53, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 53, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDO, 53, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDO, 53, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CMD_RSP, 54, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO19, 54, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 54, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDI, 54, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDI, 54, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_0, 55, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO20, 55, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 55, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TCK, 55, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TCK, 55, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_1, 56, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO21, 56, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 56, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TMS, 56, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TMS, 56, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_2, 57, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO22, 57, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_TX, 57, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SCL, 57, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DABCLK, 57, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_3, 58, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO23, 58, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 58, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_RX, 58, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SDA, 58, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DALRC, 58, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SADC_XAIN0, 59, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO26, 59, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN1, 60, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO27, 60, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN2, 61, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO24, 61, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN3, 62, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO25, 62, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO28, 63, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 63, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM10, 63, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_DBG_CLK, 63, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 63, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXEN, 63, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 63, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO29, 64, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 64, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM11, 64, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(RTC_CLK, 64, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 64, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_OE, 64, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 64, FUNC7, PUPD_NONE, 0);
+
+
+/* PINCTRL_MUX */
+
+PINCTRL_MUX(AC_I2S_CLK, 0, &PAD39_AC_I2S_CLK);
+PINCTRL_MUX(AC_I2S_DI, 0, &PAD38_AC_I2S_DI);
+PINCTRL_MUX(AC_I2S_DO, 0, &PAD37_AC_I2S_DO);
+PINCTRL_MUX(AC_I2S_WS, 0, &PAD40_AC_I2S_WS);
+PINCTRL_MUX(AC_MCLK, 0, &PAD41_AC_MCLK);
+
+PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD55_ARC_JTAG_TCK);
+PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD54_ARC_JTAG_TDI);
+PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD53_ARC_JTAG_TDO);
+PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD56_ARC_JTAG_TMS);
+PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD52_ARC_JTAG_TRSTN);
+
+PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD40_ARM_JTAG_TCK);
+PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD39_ARM_JTAG_TDI);
+PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD38_ARM_JTAG_TDO);
+PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD41_ARM_JTAG_TMS);
+PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD37_ARM_JTAG_TRSTN);
+
+PINCTRL_MUX(DW_I2S_CLK, 0, &PAD39_DW_I2S_CLK);
+PINCTRL_MUX(DW_I2S_DI, 0, &PAD38_DW_I2S_DI);
+PINCTRL_MUX(DW_I2S_DO, 0, &PAD37_DW_I2S_DO);
+PINCTRL_MUX(DW_I2S_WS, 0, &PAD40_DW_I2S_WS);
+
+PINCTRL_MUX(ETH_LINK_ACT, 1, &PAD1_ETH_LINK_ACT,
+ &PAD63_ETH_LINK_ACT);
+PINCTRL_MUX(ETH_LINK_SPD, 1, &PAD2_ETH_LINK_SPD,
+ &PAD64_ETH_LINK_SPD);
+PINCTRL_MUX(ETH_LINK_STA, 1, &PAD2_ETH_LINK_STA,
+ &PAD64_ETH_LINK_STA);
+
+PINCTRL_MUX(I2C0_SCL, 0, &PAD5_I2C0_SCL);
+PINCTRL_MUX(I2C0_SDA, 0, &PAD6_I2C0_SDA);
+
+PINCTRL_MUX(I2C1_SCL, 2, &PAD11_I2C1_SCL, &PAD30_I2C1_SCL, &PAD46_I2C1_SCL);
+PINCTRL_MUX(I2C1_SDA, 2, &PAD12_I2C1_SDA, &PAD31_I2C1_SDA, &PAD47_I2C1_SDA);
+
+PINCTRL_MUX(I2C2_SCL, 1, &PAD16_I2C2_SCL, &PAD57_I2C2_SCL);
+PINCTRL_MUX(I2C2_SDA, 1, &PAD17_I2C2_SDA, &PAD58_I2C2_SDA);
+
+PINCTRL_MUX(MAC_MDC, 0, &PAD28_MAC_MDC, &PAD63_MAC_MDC);
+PINCTRL_MUX(MAC_MDIO, 0, &PAD29_MAC_MDIO, &PAD64_MAC_MDIO);
+PINCTRL_MUX(MAC_REF_CLK, 0, &PAD21_MAC_REF_CLK);
+PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD20_MAC_RMII_CLK);
+PINCTRL_MUX(MAC_RXDV, 0, &PAD27_MAC_RXDV);
+PINCTRL_MUX(MAC_RXD_0, 0, &PAD25_MAC_RXD_0);
+PINCTRL_MUX(MAC_RXD_1, 0, &PAD26_MAC_RXD_1);
+PINCTRL_MUX(MAC_TXD_0, 0, &PAD22_MAC_TXD_0);
+PINCTRL_MUX(MAC_TXD_1, 0, &PAD23_MAC_TXD_1);
+PINCTRL_MUX(MAC_TXEN, 0, &PAD24_MAC_TXEN);
+
+PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD55_PAE_JTAG_TCK);
+PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD54_PAE_JTAG_TDI);
+PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD53_PAE_JTAG_TDO);
+PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD56_PAE_JTAG_TMS);
+PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD52_PAE_JTAG_TRSTN);
+
+PINCTRL_MUX(PWM0, 0, &PAD16_PWM0);
+PINCTRL_MUX(PWM1, 0, &PAD17_PWM1);
+PINCTRL_MUX(PWM10, 0, &PAD63_PWM10);
+PINCTRL_MUX(PWM11, 0, &PAD64_PWM11);
+PINCTRL_MUX(PWM2, 0, &PAD11_PWM2, &PAD18_PWM2, &PAD20_PWM2);
+PINCTRL_MUX(PWM3, 0, &PAD12_PWM3, &PAD19_PWM3, &PAD22_PWM3);
+PINCTRL_MUX(PWM4, 0, &PAD13_PWM4, &PAD23_PWM4);
+PINCTRL_MUX(PWM5, 0, &PAD14_PWM5, &PAD24_PWM5);
+PINCTRL_MUX(PWM6, 1, &PAD25_PWM6, &PAD37_PWM6);
+PINCTRL_MUX(PWM7, 1, &PAD26_PWM7, &PAD38_PWM7);
+PINCTRL_MUX(PWM8, 1, &PAD27_PWM8, &PAD39_PWM8);
+PINCTRL_MUX(PWM9, 1, &PAD28_PWM9, &PAD40_PWM9);
+
+PINCTRL_MUX(RTC_CLK, 0, &PAD64_RTC_CLK);
+
+PINCTRL_MUX(SADC_XAIN0, 0, &PAD59_SADC_XAIN0);
+PINCTRL_MUX(SADC_XAIN1, 0, &PAD60_SADC_XAIN1);
+PINCTRL_MUX(SADC_XAIN2, 0, &PAD61_SADC_XAIN2);
+PINCTRL_MUX(SADC_XAIN3, 0, &PAD62_SADC_XAIN3);
+
+PINCTRL_MUX(SD0_CD, 0, &PAD52_SD0_CD);
+PINCTRL_MUX(SD0_CLK, 0, &PAD53_SD0_CLK);
+PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD54_SD0_CMD_RSP);
+PINCTRL_MUX(SD0_DATA_0, 0, &PAD55_SD0_DATA_0);
+PINCTRL_MUX(SD0_DATA_1, 0, &PAD56_SD0_DATA_1);
+PINCTRL_MUX(SD0_DATA_2, 0, &PAD57_SD0_DATA_2);
+PINCTRL_MUX(SD0_DATA_3, 0, &PAD58_SD0_DATA_3);
+
+PINCTRL_MUX(SD1_CD, 0, &PAD10_SD1_CD, &PAD22_SD1_CD, &PAD31_SD1_CD,
+ &PAD41_SD1_CD, &PAD63_SD1_CD);
+PINCTRL_MUX(SD1_CLK, 0, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP, 0, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0, 0, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1, 0, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2, 0, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3, 0, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+PINCTRL_MUX(SENSOR_CLK, 0, &PAD7_SENSOR_CLK);
+
+PINCTRL_MUX(SSI0_CLK, 0, &PAD42_SSI0_CLK);
+PINCTRL_MUX(SSI0_D2, 0, &PAD46_SSI0_D2);
+PINCTRL_MUX(SSI0_D3, 0, &PAD47_SSI0_D3);
+PINCTRL_MUX(SSI0_RXD, 0, &PAD45_SSI0_RXD);
+PINCTRL_MUX(SSI0_TXD, 0, &PAD44_SSI0_TXD);
+
+PINCTRL_MUX(SSI1_CLK, 2, &PAD11_SSI1_CLK, &PAD37_SSI1_CLK, &PAD48_SSI1_CLK,
+ &PAD53_SSI1_CLK);
+PINCTRL_MUX(SSI1_RXD, 2, &PAD14_SSI1_RXD, &PAD40_SSI1_RXD, &PAD51_SSI1_RXD,
+ &PAD55_SSI1_RXD);
+PINCTRL_MUX(SSI1_TXD, 2, &PAD13_SSI1_TXD, &PAD39_SSI1_TXD, &PAD50_SSI1_TXD,
+ &PAD54_SSI1_TXD);
+
+PINCTRL_MUX(SSI2_CLK, 1, &PAD37_SSI2_CLK, &PAD48_SSI2_CLK);
+PINCTRL_MUX(SSI2_CSN_0, 1, &PAD38_SSI2_CSN_0, &PAD49_SSI2_CSN_0);
+PINCTRL_MUX(SSI2_RXD, 1, &PAD40_SSI2_RXD, &PAD51_SSI2_RXD);
+PINCTRL_MUX(SSI2_TXD, 1, &PAD39_SSI2_TXD, &PAD50_SSI2_TXD);
+
+PINCTRL_MUX(UART0_RX, 0, &PAD4_UART0_RX);
+PINCTRL_MUX(UART0_TX, 0, &PAD3_UART0_TX);
+
+PINCTRL_MUX(UART1_RX, 0, &PAD10_UART1_RX, &PAD33_UART1_RX, &PAD47_UART1_RX);
+PINCTRL_MUX(UART1_TX, 0, &PAD9_UART1_TX, &PAD32_UART1_TX, &PAD46_UART1_TX);
+
+PINCTRL_MUX(UART2_RX, 0, &PAD14_UART2_RX, &PAD17_UART2_RX, &PAD35_UART2_RX,
+ &PAD58_UART2_RX);
+PINCTRL_MUX(UART2_TX, 0, &PAD13_UART2_TX, &PAD16_UART2_TX, &PAD34_UART2_TX,
+ &PAD57_UART2_TX);
+
+PINCTRL_MUX(USB_PWREN, 0, &PAD15_USB_PWREN, &PAD41_USB_PWREN);
+
+PINCTRL_MUX(GPIO0, 0, &PAD37_GPIO0);
+PINCTRL_MUX(GPIO1, 0, &PAD38_GPIO1);
+PINCTRL_MUX(GPIO2, 0, &PAD39_GPIO2);
+PINCTRL_MUX(GPIO3, 0, &PAD40_GPIO3);
+PINCTRL_MUX(GPIO4, 0, &PAD41_GPIO4);
+PINCTRL_MUX(GPIO5, 0, &PAD42_GPIO5);
+PINCTRL_MUX(GPIO6, 0, &PAD43_GPIO6);
+PINCTRL_MUX(GPIO7, 0, &PAD44_GPIO7);
+PINCTRL_MUX(GPIO8, 0, &PAD45_GPIO8);
+PINCTRL_MUX(GPIO9, 0, &PAD46_GPIO9);
+PINCTRL_MUX(GPIO10, 0, &PAD47_GPIO10);
+PINCTRL_MUX(GPIO11, 0, &PAD48_GPIO11);
+PINCTRL_MUX(GPIO12, 0, &PAD7_GPIO12);
+PINCTRL_MUX(GPIO13, 0, &PAD8_GPIO13);
+PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14);
+PINCTRL_MUX(GPIO15, 0, &PAD50_GPIO15);
+PINCTRL_MUX(GPIO16, 0, &PAD51_GPIO16);
+PINCTRL_MUX(GPIO17, 0, &PAD52_GPIO17);
+PINCTRL_MUX(GPIO18, 0, &PAD53_GPIO18);
+PINCTRL_MUX(GPIO19, 0, &PAD54_GPIO19);
+PINCTRL_MUX(GPIO20, 0, &PAD55_GPIO20);
+PINCTRL_MUX(GPIO21, 0, &PAD56_GPIO21);
+PINCTRL_MUX(GPIO22, 0, &PAD57_GPIO22);
+PINCTRL_MUX(GPIO23, 0, &PAD58_GPIO23);
+PINCTRL_MUX(GPIO24, 0, &PAD61_GPIO24);
+PINCTRL_MUX(GPIO25, 0, &PAD62_GPIO25);
+PINCTRL_MUX(GPIO26, 0, &PAD59_GPIO26);
+PINCTRL_MUX(GPIO27, 0, &PAD60_GPIO27);
+PINCTRL_MUX(GPIO28, 0, &PAD63_GPIO28);
+PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29);
+PINCTRL_MUX(GPIO30, 0, &PAD0_GPIO30);
+PINCTRL_MUX(GPIO31, 0, &PAD1_GPIO31);
+PINCTRL_MUX(GPIO32, 0, &PAD2_GPIO32);
+PINCTRL_MUX(GPIO33, 0, &PAD3_GPIO33);
+PINCTRL_MUX(GPIO34, 0, &PAD4_GPIO34);
+PINCTRL_MUX(GPIO35, 0, &PAD5_GPIO35);
+PINCTRL_MUX(GPIO36, 0, &PAD6_GPIO36);
+PINCTRL_MUX(GPIO37, 0, &PAD11_GPIO37);
+PINCTRL_MUX(GPIO38, 0, &PAD12_GPIO38);
+PINCTRL_MUX(GPIO39, 0, &PAD9_GPIO39);
+PINCTRL_MUX(GPIO40, 0, &PAD10_GPIO40);
+PINCTRL_MUX(GPIO41, 0, &PAD13_GPIO41);
+PINCTRL_MUX(GPIO42, 0, &PAD14_GPIO42);
+PINCTRL_MUX(GPIO43, 0, &PAD16_GPIO43);
+PINCTRL_MUX(GPIO44, 0, &PAD17_GPIO44);
+PINCTRL_MUX(GPIO45, 0, &PAD18_GPIO45);
+PINCTRL_MUX(GPIO46, 0, &PAD19_GPIO46);
+PINCTRL_MUX(GPIO47, 0, &PAD15_GPIO47);
+PINCTRL_MUX(GPIO48, 0, &PAD20_GPIO48);
+PINCTRL_MUX(GPIO49, 0, &PAD22_GPIO49);
+PINCTRL_MUX(GPIO50, 0, &PAD23_GPIO50);
+PINCTRL_MUX(GPIO51, 0, &PAD24_GPIO51);
+PINCTRL_MUX(GPIO52, 0, &PAD25_GPIO52);
+PINCTRL_MUX(GPIO53, 0, &PAD26_GPIO53);
+PINCTRL_MUX(GPIO54, 0, &PAD27_GPIO54);
+PINCTRL_MUX(GPIO55, 0, &PAD28_GPIO55);
+PINCTRL_MUX(GPIO56, 0, &PAD29_GPIO56);
+PINCTRL_MUX(GPIO57, 0, &PAD30_GPIO57);
+PINCTRL_MUX(GPIO58, 0, &PAD31_GPIO58);
+PINCTRL_MUX(GPIO59, 0, &PAD32_GPIO59);
+PINCTRL_MUX(GPIO60, 0, &PAD33_GPIO60);
+PINCTRL_MUX(GPIO61, 0, &PAD34_GPIO61);
+PINCTRL_MUX(GPIO62, 0, &PAD35_GPIO62);
+PINCTRL_MUX(GPIO63, 0, &PAD36_GPIO63);
+
+PINCTRL_MUX(SD1_CLK_EMMC, 3, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP_EMMC, 3, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0_EMMC, 3, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1_EMMC, 3, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2_EMMC, 3, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3_EMMC, 3, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+/* PINCTRL_DEVICE */
+PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO,
+ &MUX_AC_I2S_WS, &MUX_AC_MCLK);
+PINCTRL_DEVICE(AC_MCLK, 1, &MUX_AC_MCLK);
+PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI,
+ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN);
+PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI,
+ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN);
+PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO,
+ &MUX_DW_I2S_WS);
+PINCTRL_DEVICE(ETH, 2, &MUX_ETH_LINK_ACT, &MUX_ETH_LINK_STA);
+PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA);
+PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA);
+PINCTRL_DEVICE(I2C2, 2, &MUX_I2C2_SCL, &MUX_I2C2_SDA);
+PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI,
+ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN);
+PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0);
+PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1);
+PINCTRL_DEVICE(PWM10, 1, &MUX_PWM10);
+PINCTRL_DEVICE(PWM11, 1, &MUX_PWM11);
+PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2);
+PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3);
+PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4);
+PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5);
+PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6);
+PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7);
+PINCTRL_DEVICE(PWM8, 1, &MUX_PWM8);
+PINCTRL_DEVICE(PWM9, 1, &MUX_PWM9);
+PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK,
+ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1,
+ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN);
+PINCTRL_DEVICE(RTC, 1, &MUX_RTC_CLK);
+PINCTRL_DEVICE(SADC_XAIN0, 1, &MUX_SADC_XAIN0);
+PINCTRL_DEVICE(SADC_XAIN1, 1, &MUX_SADC_XAIN1);
+PINCTRL_DEVICE(SADC_XAIN2, 1, &MUX_SADC_XAIN2);
+PINCTRL_DEVICE(SADC_XAIN3, 1, &MUX_SADC_XAIN3);
+PINCTRL_DEVICE(SD0, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0);
+PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_WIFI, 6, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, &MUX_SD0_DATA_0,
+ &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD1, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_1BIT_NO_WP, 4, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0);
+PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_WIFI, 6, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, &MUX_SD1_DATA_0,
+ &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SENSOR_CLK, 1, &MUX_SENSOR_CLK);
+PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_RXD,
+ &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_D2,
+ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI1, 4, &MUX_GPIO14, &MUX_SSI1_CLK, &MUX_SSI1_RXD,
+ &MUX_SSI1_TXD);
+PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN_0, &MUX_SSI2_RXD,
+ &MUX_SSI2_TXD);
+PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX);
+PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX);
+PINCTRL_DEVICE(UART2, 2, &MUX_UART2_RX, &MUX_UART2_TX);
+PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN);
+PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0);
+PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1);
+PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2);
+PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3);
+PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4);
+PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5);
+PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6);
+PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7);
+PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8);
+PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9);
+PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10);
+PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11);
+PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12);
+PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13);
+PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14);
+PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15);
+PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16);
+PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17);
+PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18);
+PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19);
+PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20);
+PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21);
+PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22);
+PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23);
+PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24);
+PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25);
+PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26);
+PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27);
+PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28);
+PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29);
+PINCTRL_DEVICE(GPIO30, 1, &MUX_GPIO30);
+PINCTRL_DEVICE(GPIO31, 1, &MUX_GPIO31);
+PINCTRL_DEVICE(GPIO32, 1, &MUX_GPIO32);
+PINCTRL_DEVICE(GPIO33, 1, &MUX_GPIO33);
+PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34);
+PINCTRL_DEVICE(GPIO35, 1, &MUX_GPIO35);
+PINCTRL_DEVICE(GPIO36, 1, &MUX_GPIO36);
+PINCTRL_DEVICE(GPIO37, 1, &MUX_GPIO37);
+PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38);
+PINCTRL_DEVICE(GPIO39, 1, &MUX_GPIO39);
+PINCTRL_DEVICE(GPIO40, 1, &MUX_GPIO40);
+PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41);
+PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42);
+PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43);
+PINCTRL_DEVICE(GPIO44, 1, &MUX_GPIO44);
+PINCTRL_DEVICE(GPIO45, 1, &MUX_GPIO45);
+PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46);
+PINCTRL_DEVICE(GPIO47, 1, &MUX_GPIO47);
+PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48);
+PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49);
+PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50);
+PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51);
+PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52);
+PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53);
+PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54);
+PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55);
+PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56);
+PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57);
+PINCTRL_DEVICE(GPIO58, 1, &MUX_GPIO58);
+PINCTRL_DEVICE(GPIO59, 1, &MUX_GPIO59);
+PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60);
+PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61);
+PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62);
+PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63);
+
+PINCTRL_DEVICE(SD1_EMMC, 6, &MUX_SD1_CLK_EMMC, &MUX_SD1_CMD_RSP_EMMC,
+ &MUX_SD1_DATA_0_EMMC, &MUX_SD1_DATA_1_EMMC, &MUX_SD1_DATA_2_EMMC,
+ &MUX_SD1_DATA_3_EMMC);
+
+void fh_pinctrl_init_devicelist(OS_LIST *list)
+{
+ OS_LIST_EMPTY(list);
+
+ /*PINCTRL_ADD_DEVICE*/
+ PINCTRL_ADD_DEVICE(ACI2S);
+ PINCTRL_ADD_DEVICE(AC_MCLK);
+ PINCTRL_ADD_DEVICE(ARCJTAG);
+ PINCTRL_ADD_DEVICE(ARMJTAG);
+ PINCTRL_ADD_DEVICE(DWI2S);
+ PINCTRL_ADD_DEVICE(ETH);
+ PINCTRL_ADD_DEVICE(I2C0);
+ PINCTRL_ADD_DEVICE(I2C1);
+ PINCTRL_ADD_DEVICE(I2C2);
+ PINCTRL_ADD_DEVICE(PAEJTAG);
+ PINCTRL_ADD_DEVICE(PWM0);
+ PINCTRL_ADD_DEVICE(PWM1);
+ PINCTRL_ADD_DEVICE(PWM10);
+ PINCTRL_ADD_DEVICE(PWM11);
+ PINCTRL_ADD_DEVICE(PWM2);
+ PINCTRL_ADD_DEVICE(PWM3);
+ PINCTRL_ADD_DEVICE(PWM4);
+ PINCTRL_ADD_DEVICE(PWM5);
+ PINCTRL_ADD_DEVICE(PWM6);
+ PINCTRL_ADD_DEVICE(PWM7);
+ PINCTRL_ADD_DEVICE(PWM8);
+ PINCTRL_ADD_DEVICE(PWM9);
+ PINCTRL_ADD_DEVICE(RMII);
+ PINCTRL_ADD_DEVICE(RTC);
+ PINCTRL_ADD_DEVICE(SADC_XAIN0);
+ PINCTRL_ADD_DEVICE(SADC_XAIN1);
+ PINCTRL_ADD_DEVICE(SADC_XAIN2);
+ PINCTRL_ADD_DEVICE(SADC_XAIN3);
+ PINCTRL_ADD_DEVICE(SD0);
+ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_WIFI);
+ PINCTRL_ADD_DEVICE(SD1);
+ PINCTRL_ADD_DEVICE(SD1_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_WIFI);
+ PINCTRL_ADD_DEVICE(SENSOR_CLK);
+ PINCTRL_ADD_DEVICE(SSI0);
+ PINCTRL_ADD_DEVICE(SSI0_4BIT);
+ PINCTRL_ADD_DEVICE(SSI1);
+ PINCTRL_ADD_DEVICE(SSI2);
+ PINCTRL_ADD_DEVICE(UART0);
+ PINCTRL_ADD_DEVICE(UART1);
+ PINCTRL_ADD_DEVICE(UART2);
+ PINCTRL_ADD_DEVICE(USB);
+ PINCTRL_ADD_DEVICE(GPIO0);
+ PINCTRL_ADD_DEVICE(GPIO1);
+ PINCTRL_ADD_DEVICE(GPIO2);
+ PINCTRL_ADD_DEVICE(GPIO3);
+ PINCTRL_ADD_DEVICE(GPIO4);
+ PINCTRL_ADD_DEVICE(GPIO5);
+ PINCTRL_ADD_DEVICE(GPIO6);
+ PINCTRL_ADD_DEVICE(GPIO7);
+ PINCTRL_ADD_DEVICE(GPIO8);
+ PINCTRL_ADD_DEVICE(GPIO9);
+ PINCTRL_ADD_DEVICE(GPIO10);
+ PINCTRL_ADD_DEVICE(GPIO11);
+ PINCTRL_ADD_DEVICE(GPIO12);
+ PINCTRL_ADD_DEVICE(GPIO13);
+ PINCTRL_ADD_DEVICE(GPIO14);
+ PINCTRL_ADD_DEVICE(GPIO15);
+ PINCTRL_ADD_DEVICE(GPIO16);
+ PINCTRL_ADD_DEVICE(GPIO17);
+ PINCTRL_ADD_DEVICE(GPIO18);
+ PINCTRL_ADD_DEVICE(GPIO19);
+ PINCTRL_ADD_DEVICE(GPIO20);
+ PINCTRL_ADD_DEVICE(GPIO21);
+ PINCTRL_ADD_DEVICE(GPIO22);
+ PINCTRL_ADD_DEVICE(GPIO23);
+ PINCTRL_ADD_DEVICE(GPIO24);
+ PINCTRL_ADD_DEVICE(GPIO25);
+ PINCTRL_ADD_DEVICE(GPIO26);
+ PINCTRL_ADD_DEVICE(GPIO27);
+ PINCTRL_ADD_DEVICE(GPIO28);
+ PINCTRL_ADD_DEVICE(GPIO29);
+ PINCTRL_ADD_DEVICE(GPIO30);
+ PINCTRL_ADD_DEVICE(GPIO31);
+ PINCTRL_ADD_DEVICE(GPIO32);
+ PINCTRL_ADD_DEVICE(GPIO33);
+ PINCTRL_ADD_DEVICE(GPIO34);
+ PINCTRL_ADD_DEVICE(GPIO35);
+ PINCTRL_ADD_DEVICE(GPIO36);
+ PINCTRL_ADD_DEVICE(GPIO37);
+ PINCTRL_ADD_DEVICE(GPIO38);
+ PINCTRL_ADD_DEVICE(GPIO39);
+ PINCTRL_ADD_DEVICE(GPIO40);
+ PINCTRL_ADD_DEVICE(GPIO41);
+ PINCTRL_ADD_DEVICE(GPIO42);
+ PINCTRL_ADD_DEVICE(GPIO43);
+ PINCTRL_ADD_DEVICE(GPIO44);
+ PINCTRL_ADD_DEVICE(GPIO45);
+ PINCTRL_ADD_DEVICE(GPIO46);
+ PINCTRL_ADD_DEVICE(GPIO47);
+ PINCTRL_ADD_DEVICE(GPIO48);
+ PINCTRL_ADD_DEVICE(GPIO49);
+ PINCTRL_ADD_DEVICE(GPIO50);
+ PINCTRL_ADD_DEVICE(GPIO51);
+ PINCTRL_ADD_DEVICE(GPIO52);
+ PINCTRL_ADD_DEVICE(GPIO53);
+ PINCTRL_ADD_DEVICE(GPIO54);
+ PINCTRL_ADD_DEVICE(GPIO55);
+ PINCTRL_ADD_DEVICE(GPIO56);
+ PINCTRL_ADD_DEVICE(GPIO57);
+ PINCTRL_ADD_DEVICE(GPIO58);
+ PINCTRL_ADD_DEVICE(GPIO59);
+ PINCTRL_ADD_DEVICE(GPIO60);
+ PINCTRL_ADD_DEVICE(GPIO61);
+ PINCTRL_ADD_DEVICE(GPIO62);
+ PINCTRL_ADD_DEVICE(GPIO63);
+
+ PINCTRL_ADD_DEVICE(SD1_EMMC);
+}
+
+char *fh_pinctrl_selected_devices[] =
+{
+ CONFIG_PINCTRL_SELECT
+};
diff --git a/arch/arm/mach-fh/fh8856v200/Makefile b/arch/arm/mach-fh/fh8856v200/Makefile
new file mode 100644
index 00000000..1443fdae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v200/Makefile
@@ -0,0 +1 @@
+obj-y += board.o chip.o
\ No newline at end of file
diff --git a/arch/arm/mach-fh/fh8856v200/board.c b/arch/arm/mach-fh/fh8856v200/board.c
new file mode 100644
index 00000000..2b9fa6de
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v200/board.c
@@ -0,0 +1,1165 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/phy.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/eeprom.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/if_alg.h>
+#include <linux/mmc/host.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/io.h>
+#include <mach/board_config.h>
+#include <mach/pinctrl.h>
+#include <mach/clock.h>
+#include <mach/fh_uart_plat.h>
+#include <mach/fh_mci_plat.h>
+#include <mach/fh_gmac_plat.h>
+#include <mach/fh_gpio_plat.h>
+#include <mach/fh_efuse_plat.h>
+#include <mach/fh_dma_plat.h>
+#include <mach/fh_spi_plat.h>
+#include <mach/fh_i2s_plat.h>
+#include <mach/fh_pwm_plat.h>
+#include <mach/fh_wdt_plat.h>
+#include <mach/fh_usb_plat.h>
+#include <mach/fh_sadc_plat.h>
+#include <mach/fh_rtc_plat.h>
+#include "chip.h"
+
+struct uart_port fh_serial_ports[FH_UART_NUMBER];
+
+static struct map_desc fh8856v200_io_desc[] = {
+ {
+ .virtual = VA_RAM_REG_BASE,
+ .pfn = __phys_to_pfn(RAM_BASE),
+ .length = SZ_16K,
+ .type = MT_MEMORY_RWX,
+ },
+ {
+ .virtual = VA_DDRC_REG_BASE,
+ .pfn = __phys_to_pfn(DDRC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_INTC_REG_BASE,
+ .pfn = __phys_to_pfn(INTC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_TIMER_REG_BASE,
+ .pfn = __phys_to_pfn(TIMER_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_PMU_REG_BASE,
+ .pfn = __phys_to_pfn(PMU_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART0_REG_BASE,
+ .pfn = __phys_to_pfn(UART0_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART1_REG_BASE,
+ .pfn = __phys_to_pfn(UART1_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART2_REG_BASE,
+ .pfn = __phys_to_pfn(UART2_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+
+};
+
+static struct resource fh_gpio0_resources[] = {
+ {
+ .start = GPIO0_REG_BASE,
+ .end = GPIO0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO0_IRQ,
+ .end = GPIO0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gpio1_resources[] = {
+ {
+ .start = GPIO1_REG_BASE,
+ .end = GPIO1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO1_IRQ,
+ .end = GPIO1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart0_resources[] = {
+ {
+ .start = (UART0_REG_BASE),
+ .end = (UART0_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = UART0_IRQ,
+ .end = UART0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart1_resources[] = {
+ {
+ .start = (UART1_REG_BASE),
+ .end = (UART1_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART1_IRQ,
+ .end = UART1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_uart2_resources[] = {
+ {
+ .start = (UART2_REG_BASE),
+ .end = (UART2_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART2_IRQ,
+ .end = UART2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+static struct resource fh_sdc0_resources[] = {
+ {
+ .start = SDC0_REG_BASE,
+ .end = SDC0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC0_IRQ,
+ .end = SDC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_sdc1_resources[] = {
+ {
+ .start = SDC1_REG_BASE,
+ .end = SDC1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC1_IRQ,
+ .end = SDC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gmac_resources[] = {
+ {
+ .start = GMAC_REG_BASE,
+ .end = GMAC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GMAC_IRQ,
+ .end = GMAC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource fh_wdt_resources[] = {
+ {
+ .start = WDT_REG_BASE,
+ .end = WDT_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = WDT_IRQ,
+ .end = WDT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct resource fh_perf_resources[] = {
+ {
+ .start = PMU_REG_BASE,
+ .end = PMU_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PERF_IRQ,
+ .end = PERF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+
+static struct fh_gmac_platform_data fh_gmac_data = {
+ .phy_reset_pin = 29,
+};
+
+static struct fh_uart_dma uart1_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART1_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART1_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART1_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART1_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+static struct fh_uart_dma uart2_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART2_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART2_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART2_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART2_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+
+static struct fh_platform_uart fh_uart_platform_data[] = {
+ {
+ .mapbase = UART0_REG_BASE,
+ .fifo_size = 16,
+ .irq = UART0_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = NULL,
+ },
+ {
+ .mapbase = UART1_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART1_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart1_dma_info,
+ },
+ {
+ .mapbase = UART2_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART2_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart2_dma_info,
+ },
+};
+
+static struct resource fh_pwm_resources[] = {
+ {
+ .start = PWM_REG_BASE,
+ .end = PWM_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PWM_IRQ,
+ .end = PWM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_i2c_resources_0[] = {
+ {
+ .start = I2C0_REG_BASE,
+ .end = I2C0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C0_IRQ,
+ .end = I2C0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_1[] = {
+ {
+ .start = I2C1_REG_BASE,
+ .end = I2C1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C1_IRQ,
+ .end = I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_2[] = {
+ {
+ .start = I2C2_REG_BASE,
+ .end = I2C2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C2_IRQ,
+ .end = I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_rtc_resources[] = {
+ {
+ .start = RTC_REG_BASE,
+ .end = RTC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio0_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO0",
+ .base = 0,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio1_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO1",
+ .base = 32,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_pwm_data pwm_data = {
+ .npwm = 12,
+};
+
+static struct resource fh_sadc_resources[] = {
+ {
+ .start = SADC_REG_BASE,
+ .end = SADC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SADC_IRQ,
+ .end = SADC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_aes_resources[] = {
+ {
+ .start = AES_REG_BASE,
+ .end = AES_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = AES_IRQ,
+ .end = AES_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_efuse_resources[] = {
+ {
+ .start = EFUSE_REG_BASE,
+ .end = EFUSE_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct resource fh_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+static struct resource fh_axi_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+static struct resource fh_spi0_resources[] = {
+ {
+ .start = SPI0_REG_BASE,
+ .end = SPI0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI0_IRQ,
+ .end = SPI0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi1_resources[] = {
+ {
+ .start = SPI1_REG_BASE,
+ .end = SPI1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI1_IRQ,
+ .end = SPI1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi2_resources[] = {
+ {
+ .start = SPI2_REG_BASE,
+ .end = SPI2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "fh spi2 mem",
+ },
+ {
+ .start = SPI2_IRQ,
+ .end = SPI2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ .name = "fh spi2 irq",
+ },
+};
+
+static struct resource fh_usb_resources[] = {
+ {
+ .start = USBC_REG_BASE,
+ .end = USBC_REG_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USBC_IRQ,
+ .end = USBC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static unsigned int fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+
+struct fh_mci_board fh_mci = {
+ .num_slots = 1,
+ .get_cd = fh_mci_sys_card_detect_fixed,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+ .rescan_max_num = 2,
+};
+
+struct fh_mci_board fh_mci_sd = {
+ .num_slots = 1,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+};
+
+static struct platform_device fh_gmac_device = {
+ .name = "fh_gmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gmac_resources),
+ .resource = fh_gmac_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_gmac_data,
+ },
+};
+
+struct platform_device fh_sd0_device = {
+ .name = "fh_mci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sdc0_resources),
+ .resource = fh_sdc0_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci_sd,
+ }
+};
+
+struct platform_device fh_sd1_device = {
+ .name = "fh_mci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_sdc1_resources),
+ .resource = fh_sdc1_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci,
+ }
+};
+
+struct fh_sadc_platform_data fh_sadc_data = {
+ .ref_vol = 1800,
+ .active_bit = 0xfff,
+};
+
+static struct platform_device fh_sadc_device = {
+ .name = "fh_sadc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sadc_resources),
+ .resource = fh_sadc_resources,
+ .dev = {
+ .platform_data = &fh_sadc_data,
+ },
+};
+
+static struct platform_device fh_uart0_device = {
+ .name = "ttyS",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_uart0_resources),
+ .resource = fh_uart0_resources,
+ .dev.platform_data = &fh_uart_platform_data[0],
+};
+
+static struct platform_device fh_uart1_device = {
+ .name = "ttyS",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_uart1_resources),
+ .resource = fh_uart1_resources,
+ .dev.platform_data = &fh_uart_platform_data[1],
+};
+
+static struct platform_device fh_uart2_device = {
+ .name = "ttyS",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_uart2_resources),
+ .resource = fh_uart2_resources,
+ .dev.platform_data = &fh_uart_platform_data[2],
+};
+
+static struct platform_device fh_pinctrl_device = {
+ .name = "fh_pinctrl",
+ .id = 0,
+};
+
+static struct platform_device fh_i2c0_device = {
+ .name = "fh_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_0),
+ .resource = fh_i2c_resources_0,
+};
+
+static struct platform_device fh_i2c1_device = {
+ .name = "fh_i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_1),
+ .resource = fh_i2c_resources_1,
+};
+
+static struct platform_device fh_i2c2_device = {
+ .name = "fh_i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_2),
+ .resource = fh_i2c_resources_2,
+};
+
+static struct fh_rtc_plat_data rtc_plat_data[] = {
+ {
+ .lut_cof = 58,
+ .lut_offset = 0xff,
+ .tsensor_cp_default_out = 0x993,
+ .clk_name = "rtc_hclk_gate",
+ },
+ {
+ .lut_cof = 71,
+ .lut_offset = 0xf6,
+ .tsensor_cp_default_out = 0x9cc,
+ .clk_name = "rtc_hclk_gate",
+ }
+};
+
+static struct platform_device fh_rtc_device = {
+ .name = "fh_rtc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_rtc_resources),
+ .resource = fh_rtc_resources,
+ .dev.platform_data = &rtc_plat_data[0],
+};
+
+static struct resource fh_i2s_resources[] = {
+ {
+ .start = I2S_REG_BASE,
+ .end = I2S_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ACW_REG_BASE,
+ .end = ACW_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = I2S0_IRQ,
+ .end = I2S0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_i2s_platform_data fh_i2s_data = {
+ .dma_capture_channel = 4,
+ .dma_playback_channel = 5,
+ .dma_master = 0,
+ .dma_rx_hs_num = 10,
+ .dma_tx_hs_num = 11,
+ .clk = "i2s_clk",
+ .acodec_mclk = "ac_clk",
+};
+
+static struct platform_device fh_i2s_device = {
+ .name = "fh_audio",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2s_resources),
+ .resource = fh_i2s_resources,
+ .dev = {
+ .platform_data = &fh_i2s_data,
+ },
+};
+
+static struct platform_device fh_gpio0_device = {
+ .name = GPIO_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gpio0_resources),
+ .resource = fh_gpio0_resources,
+ .dev = {
+ .platform_data = &fh_gpio0_chip,
+ },
+};
+
+static struct platform_device fh_gpio1_device = {
+ .name = GPIO_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_gpio1_resources),
+ .resource = fh_gpio1_resources,
+ .dev = {
+ .platform_data = &fh_gpio1_chip,
+ },
+};
+
+static struct platform_device fh_aes_device = {
+ .name = "fh_aes",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_aes_resources),
+ .resource = fh_aes_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+struct fh_efuse_platform_data fh_efuse_plat_data = {
+ .efuse_support_flag = CRYPTO_CPU_SET_KEY |
+ CRYPTO_EX_MEM_SET_KEY |
+ CRYPTO_EX_MEM_SWITCH_KEY |
+ CRYPTO_EX_MEM_4_ENTRY_1_KEY |
+ CRYPTO_EX_MEM_INDEP_POWER,
+};
+
+
+
+#define FH_SPI0_CS0 (6)
+#define FH_SPI0_CS1 (55)
+
+#define FH_SPI1_CS0 (14)
+#define FH_SPI1_CS1 (57)
+
+#define SPI0_FIFO_DEPTH (128)
+#define SPI0_CLK_IN (200000000)
+#define SPI0_MAX_SLAVE_NO (2)
+#define SPI0_DMA_RX_CHANNEL (0)
+#define SPI0_DMA_TX_CHANNEL (1)
+
+#define SPI1_FIFO_DEPTH (64)
+#define SPI1_CLK_IN (100000000)
+#define SPI1_MAX_SLAVE_NO (2)
+#define SPI1_DMA_RX_CHANNEL (2)
+#define SPI1_DMA_TX_CHANNEL (3)
+
+#define SPI2_CLK_IN (100000000)
+
+/* SPI_TRANSFER_USE_DMA */
+static struct fh_spi_platform_data fh_spi0_data = {
+ .bus_no = 0,
+ .apb_clock_in = SPI0_CLK_IN,
+ .clock_source = {100000000, 150000000, 200000000},
+ .clock_source_num = 3,
+ .slave_max_num = SPI0_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI0_CS0,
+ .cs_data[0].name = "spi0_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI0_CS1,
+ .cs_data[1].name = "spi0_cs1",
+ .clk_name = "spi0_clk",
+ .dma_transfer_enable = SPI_TRANSFER_USE_DMA,
+ .rx_dma_channel = SPI0_DMA_RX_CHANNEL,
+ .rx_handshake_num = 4,
+ /*dma use inc mode could move data by burst mode...*/
+ /*or move data use single mode with low efficient*/
+ .ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |
+ MULTI_WIRE_SUPPORT,
+};
+
+static struct fh_spi_platform_data fh_spi1_data = {
+ .bus_no = 1,
+ .apb_clock_in = SPI1_CLK_IN,
+ .clock_source = {SPI1_CLK_IN},
+ .clock_source_num = 1,
+ .slave_max_num = SPI1_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI1_CS0,
+ .cs_data[0].name = "spi1_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI1_CS1,
+ .cs_data[1].name = "spi1_cs1",
+ .clk_name = "spi1_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct fh_spi_platform_data fh_spi2_data = {
+ .apb_clock_in = SPI2_CLK_IN,
+ .dma_transfer_enable = 0,
+ .rx_handshake_num = 12,
+ .clk_name = "spi2_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct platform_device fh_efuse_device = {
+ .name = "fh_efuse",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_efuse_resources),
+ .resource = fh_efuse_resources,
+ .dev = {
+ .platform_data = &fh_efuse_plat_data,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct fh_dma_platform_data fh_dma_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .nr_channels = 6,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_dma_device = {
+ .name = "fh_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_dma_resources),
+ .resource = fh_dma_resources,
+ .dev = {
+ .platform_data = &fh_dma_data,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+struct fh_axi_dma_platform_data axi_dma_plat_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_axi_dma_device = {
+ .name = "fh_axi_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_axi_dma_resources),
+ .resource = fh_axi_dma_resources,
+ .dev = {
+ .platform_data = &axi_dma_plat_data,
+ },
+};
+#endif
+
+
+
+static struct platform_device fh_spi0_device = {
+ .name = "fh_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi0_resources),
+ .resource = fh_spi0_resources,
+ .dev = {
+ .platform_data = &fh_spi0_data,
+ },
+};
+
+static struct platform_device fh_spi1_device = {
+ .name = "fh_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_spi1_resources),
+ .resource = fh_spi1_resources,
+ .dev = {
+ .platform_data = &fh_spi1_data,
+ },
+};
+
+static struct platform_device fh_spi2_device = {
+ .name = "fh_spi_slave",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi2_resources),
+ .resource = fh_spi2_resources,
+ .dev = {
+ .platform_data = &fh_spi2_data,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct platform_device fh_perf_device = {
+ .name = "fh_perf_mon",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_perf_resources),
+ .resource = fh_perf_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+static struct fh_wdt_platform_data fh_wdt_data = {
+ .mode = MODE_DISCRETE,
+};
+
+struct platform_device fh_wdt_device = {
+ .name = "fh_wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_wdt_resources),
+ .resource = fh_wdt_resources,
+ .dev = {
+ .platform_data = &fh_wdt_data,
+ }
+};
+
+static struct platform_device fh_pwm_device = {
+ .name = "fh_pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_pwm_resources),
+ .resource = fh_pwm_resources,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
+};
+
+static struct fh_usb_platform_data fh_usb_data = {
+ .dr_mode = "host",
+ .vbus_pwren = 47,
+};
+
+struct platform_device fh_usb_device = {
+ .name = "fh_usb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_usb_resources),
+ .resource = fh_usb_resources,
+ .dev = {
+ .platform_data = &fh_usb_data,
+ }
+};
+
+#ifdef CONFIG_FH_TSENSOR
+struct platform_device fh_tsensor_device = {
+ .name = "fh_tsensor",
+ .id = 0,
+};
+#endif
+
+static struct platform_device *fh8856v200_devices[] __initdata = {
+ &fh_uart0_device,
+ &fh_uart1_device,
+ &fh_uart2_device,
+ &fh_pinctrl_device,
+ &fh_i2c0_device,
+ &fh_i2c1_device,
+ &fh_i2c2_device,
+ &fh_rtc_device,
+ &fh_sd0_device,
+ &fh_sd1_device,
+ &fh_sadc_device,
+ &fh_gmac_device,
+ &fh_gpio0_device,
+ &fh_gpio1_device,
+ &fh_aes_device,
+ &fh_efuse_device,
+#ifdef CONFIG_FH_DMAC
+ &fh_dma_device,
+#endif
+#ifdef CONFIG_FH_AXI_DMAC
+ &fh_axi_dma_device,
+#endif
+ &fh_spi0_device,
+ &fh_spi1_device,
+ &fh_spi2_device,
+ &fh_i2s_device,
+ &fh_pwm_device,
+ &fh_wdt_device,
+ &fh_usb_device,
+#ifdef CONFIG_FH_PERF_MON
+ &fh_perf_device,
+#endif
+#ifdef CONFIG_FH_TSENSOR
+ &fh_tsensor_device,
+#endif
+};
+
+static struct mtd_partition fh_sf_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* Ramboot & U-Boot environment */
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* U-Boot */
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi_flash:256k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),4M(kernel),
+ * 8M(rootfs),
+ * -(app) */
+ /* two blocks with bad block table (and mirror) at the end */
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct mtd_partition fh_sf_nand_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_512K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi0.0:64k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),
+ * 4M(kernel),
+ * 8M(rootfs),
+ * -(app)
+ * two blocks with bad block table (and mirror) at the end
+ */
+};
+#endif
+
+static struct flash_platform_data fh_flash_platform_data = {
+ .name = "spi_flash",
+ .parts = fh_sf_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_parts),
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct flash_platform_data fh_nandflash_platform_data = {
+ .name = "spi_nandflash",
+ .parts = fh_sf_nand_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_nand_parts),
+};
+#endif
+
+static struct spi_board_info fh_spi_devices[] = {
+#ifdef CONFIG_MTD_SPI_NAND
+ {
+ .modalias = "spi-nand",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &fh_nandflash_platform_data,
+ },
+#endif
+ {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ /* multi wire should adapt spi para 'ctl_wire_support'*/
+ .mode = SPI_MODE_3 | SPI_RX_DUAL,
+ .max_speed_hz = 50000000,
+ .platform_data = &fh_flash_platform_data,
+ },
+
+};
+
+extern void early_print(const char *str, ...);
+
+static void __init fh_console_pre_init(struct fh_platform_uart *plat, int num)
+{
+ int idx = 0;
+
+ for (; idx < num; idx++) {
+ struct uart_port *port;
+
+ port = &fh_serial_ports[idx];
+ port->mapbase = plat[idx].mapbase;
+ port->fifosize = plat[idx].fifo_size;
+ port->uartclk = plat[idx].uartclk;
+
+ switch (idx) {
+ case 0:
+ port->membase = (unsigned char *)VA_UART0_REG_BASE;
+ break;
+ case 1:
+ port->membase = (unsigned char *)VA_UART1_REG_BASE;
+ break;
+ case 2:
+ port->membase = (unsigned char *)VA_UART2_REG_BASE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void __init fh8856v200_map_io(void)
+{
+ iotable_init(fh8856v200_io_desc, ARRAY_SIZE(fh8856v200_io_desc));
+ fh_console_pre_init(fh_uart_platform_data,
+ ARRAY_SIZE(fh_uart_platform_data));
+}
+
+
+static __init void fh8856v200_board_init(void)
+{
+ if (fh_is_8856v210())
+ fh_rtc_device.dev.platform_data = &rtc_plat_data[1];
+ platform_add_devices(fh8856v200_devices,
+ ARRAY_SIZE(fh8856v200_devices));
+ spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices));
+}
+void __init fh_timer_init_no_of(unsigned int iovbase,
+ unsigned int irqno);
+
+static void __init fh8856v200_init_early(void)
+{
+ fh_pmu_init();
+ fh_pinctrl_init(VA_PMU_REG_BASE + 0x80);
+}
+
+static void __init fh_time_init(void)
+{
+ unsigned int vtimerbase = (unsigned int)ioremap(TIMER_REG_BASE, SZ_4K);
+
+ fh_clk_init();
+ fh_timer_init_no_of(vtimerbase, TMR0_IRQ);
+
+}
+
+void __init fh_intc_init_no_of(unsigned int iovbase);
+static void __init fh_intc_init(void)
+{
+ unsigned int vintcbase = (unsigned int)ioremap(INTC_REG_BASE, SZ_4K);
+
+ fh_intc_init_no_of(vintcbase);
+
+}
+static void fh8856v200_restart
+ (enum reboot_mode mode, const char *cmd)
+{
+ fh_pmu_restart();
+}
+
+
+MACHINE_START(FH8856V200, "FH8856V200")
+ .atag_offset = 0x100,
+ .map_io = fh8856v200_map_io,
+ .init_irq = fh_intc_init,
+ .init_time = fh_time_init,
+ .init_machine = fh8856v200_board_init,
+ .init_early = fh8856v200_init_early,
+ .restart = fh8856v200_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-fh/fh8856v200/board_config.fh8856v200.appboard b/arch/arm/mach-fh/fh8856v200/board_config.fh8856v200.appboard
new file mode 100644
index 00000000..1c1a9153
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v200/board_config.fh8856v200.appboard
@@ -0,0 +1,45 @@
+#ifndef BOARD_CONFIG_H_
+#define BOARD_CONFIG_H_
+
+/*
+ * GPIO0 -> IRCUT_ON
+ * GPIO1 -> IRCUT_OFF
+ * GPIO2 -> USB_PWREN
+ * GPIO11 -> EMAC PHY Reset
+ * GPIO12 -> CIS_CLK
+ * GPIO13 -> CIS_RSTN
+ * GPIO14 -> CIS_PDN
+ * GPIO19 -> SD1_PWREN/WIFI_REG_ON
+ * GPIO20 -> AK7755 Reset
+ * GPIO24 -> LED0
+ * GPIO25 -> LED1
+ * GPIO26 -> Reset Configs
+ * GPIO27 -> AK7755 PowerDown
+ * GPIO28 -> IR
+ * GPIO53 -> USB_PWREN/SD0_PWREN
+ * GPIO55 -> SD1 WIFI Interrupt
+ */
+
+#define CONFIG_SD_CD_FIXED
+
+#define CONFIG_ISP_CLK_RATE 171000000
+#define CONFIG_JPEG_CLK_RATE 171000000
+#define CONFIG_VEU_CLK_RATE 240000000
+
+#define USB_VBUS_PWR_GPIO (47)
+
+#define ETH_GPIO "ETH", "GPIO48", "GPIO49", "GPIO50", "GPIO51", "GPIO52",\
+ "GPIO53", "GPIO54", "GPIO55", "GPIO56"
+
+#define CONFIG_PINCTRL_SELECT \
+ ETH_GPIO, "I2C0", "PWM2", "PWM3", "PWM4", "PWM5", "PWM6", \
+ "PWM7", "PWM8", "PWM9", "SADC_XAIN0", "SADC_XAIN1", \
+ "SD0_NO_WP", "SENSOR_CLK", "SSI0_4BIT", "UART0", \
+ "UART1", "GPIO4", "GPIO13", "GPIO30", "GPIO31", \
+ "GPIO32", "GPIO43", "GPIO44", "GPIO47", \
+\
+ "GPIO11", "GPIO14", "GPIO15", "GPIO16", "GPIO24", \
+ "GPIO25", "GPIO45", "GPIO46", "GPIO57", "GPIO58", "GPIO59", \
+ "GPIO60", "GPIO61", "GPIO62", "GPIO63"
+
+#endif /* BOARD_CONFIG_H_ */
diff --git a/arch/arm/mach-fh/fh8856v200/chip.c b/arch/arm/mach-fh/fh8856v200/chip.c
new file mode 100644
index 00000000..9bbb3c49
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v200/chip.c
@@ -0,0 +1,747 @@
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/clock.h>
+#include <mach/board_config.h>
+
+/*
+ * external oscillator
+ * fixed to 24M
+ */
+static struct fh_clk osc_clk = {
+ .name = "osc_clk",
+ .frequency = OSC_FREQUENCY,
+ .flag = CLOCK_FIXED,
+};
+
+/*
+ * phase-locked-loop device,
+ * generates a higher frequency clock
+ * from the external oscillator reference
+ *PLL_DDR
+ */
+
+static struct fh_clk pll_ddr_rclk = {
+ .name = "pll_ddr_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL0,
+ .en_reg_offset = REG_PMU_PLL0_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_CPU*/
+static struct fh_clk pll_cpu_pclk = {
+ .name = "pll_cpu_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+static struct fh_clk pll_cpu_rclk = {
+ .name = "pll_cpu_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_SYS*/
+static struct fh_clk pll_sys_pclk = {
+ .name = "pll_sys_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+
+static struct fh_clk pll_sys_rclk = {
+ .name = "pll_sys_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+static struct fh_clk pllsysp_div12_clk = {
+ .name = "pllsysp_div12_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk ddr_clk = {
+ .name = "ddr_clk",
+ .flag = CLOCK_NODIV,
+ .parent = {&pll_ddr_rclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8,
+};
+static struct fh_clk arm_clk = {
+ .name = "arm_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NOGATE|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1,
+};
+static struct fh_clk arc_clk = {
+ .name = "arc_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400000,
+};
+static struct fh_clk ahb_clk = {
+ .name = "ahb_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&osc_clk, &pll_sys_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf0000,
+};
+
+static struct fh_clk isp_aclk = {
+ .name = "isp_aclk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1,
+ .def_rate = CONFIG_ISP_CLK_RATE,
+};
+static struct fh_clk ispb_aclk = {
+ .name = "ispb_aclk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4,
+};
+
+static struct fh_clk vpu_clk = {
+ .name = "vpu_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80000000,
+};
+
+static struct fh_clk pix_clk = {
+ .name = "pix_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk jpeg_clk = {
+ .name = "jpeg_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x40000000,
+ .def_rate = CONFIG_JPEG_CLK_RATE,
+};
+
+static struct fh_clk bgm_clk = {
+ .name = "bgm_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x40000,
+};
+
+static struct fh_clk jpeg_adapt_clk = {
+ .name = "jpeg_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&jpeg_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2,
+};
+static struct fh_clk spi0_clk = {
+ .name = "spi0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100,
+};
+static struct fh_clk sdc0_clk = {
+ .name = "sdc0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x4,
+};
+static struct fh_clk spi2_clk = {
+ .name = "spi2_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100000,
+};
+static struct fh_clk spi1_clk = {
+ .name = "spi1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x200,
+};
+static struct fh_clk sdc1_clk = {
+ .name = "sdc1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x2,
+};
+
+static struct fh_clk veu_clk = {
+ .name = "veu_clk",
+ .flag = CLOCK_MULTI_PARENT,
+ .parent = {&pll_sys_pclk, &pll_sys_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x4,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0x7000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000000,
+ .def_rate = CONFIG_VEU_CLK_RATE,
+
+};
+
+static struct fh_clk veu_adapt_clk = {
+ .name = "veu_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&veu_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000000,
+
+};
+
+static struct fh_clk cis_clk_out = {
+ .name = "cis_clk_out",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800000,
+};
+
+static struct fh_clk eth_clk = {
+ .name = "eth_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x12000000,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x20000,
+};
+static struct fh_clk i2c0_clk = {
+ .name = "i2c0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400,
+};
+
+static struct fh_clk i2c1_clk = {
+ .name = "i2c1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800,
+};
+
+static struct fh_clk i2c2_clk = {
+ .name = "i2c2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x00003f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x00000008,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20000000,
+};
+
+static struct fh_clk pwm_clk = {
+ .name = "pwm_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x80,
+ .def_rate = 50000000,
+};
+
+static struct fh_clk uart0_clk = {
+ .name = "uart0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x4000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk uart1_clk = {
+ .name = "uart1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000,
+ .def_rate = 16666666,
+};
+static struct fh_clk uart2_clk = {
+ .name = "uart2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = 0,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x7f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk efuse_clk = {
+ .name = "efuse_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800000,
+};
+
+static struct fh_clk pts_clk = {
+ .name = "pts_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = CLOCK_NORESET,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0x1ff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL2,
+ .rst_reg_mask = 0x1,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk tmr0_clk = {
+ .name = "tmr0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x40000,
+};
+
+static struct fh_clk sadc_clk = {
+ .name = "sadc_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x7f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10000,
+};
+
+static struct fh_clk ac_clk = {
+ .name = "ac_clk",
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1000,
+};
+
+static struct fh_clk i2s_clk = {
+ .name = "i2s_clk",
+ .parent = {&ac_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000,
+};
+
+static struct fh_clk wdt_clk = {
+ .name = "wdt_clk",
+ .flag = 0,
+ .parent = {&ahb_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff00,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_APB_CTRL,
+ .rst_reg_mask = 0x100000,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk gpio0_db_clk = {
+ .name = "gpio0_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio1_db_clk = {
+ .name = "gpio1_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff0000,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x80000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20,
+};
+
+
+static struct fh_clk mipi_dphy_clk = {
+ .name = "mipi_dphy_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100000,
+};
+static struct fh_clk mipi_wrap_gate = {
+ .name = "mipi_wrap_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk rtc_hclk_gate = {
+ .name = "rtc_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk emac_hclk_gate = {
+ .name = "emac_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk usb_clk = {
+ .name = "usb_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk aes_hclk_gate = {
+ .name = "aes_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80,
+};
+static struct fh_clk ephy_clk_gate = {
+ .name = "ephy_clk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1,
+};
+static struct fh_clk sdc0_clk8x_gate = {
+ .name = "sdc0_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4,
+};
+static struct fh_clk sdc1_clk8x_gate = {
+ .name = "sdc1_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8,
+};
+static struct fh_clk mipic_pclk_gate = {
+ .name = "mipic_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio0_pclk_gate = {
+ .name = "gpio0_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x4000,
+};
+static struct fh_clk gpio1_pclk_gate = {
+ .name = "gpio1_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x40000000,
+};
+static struct fh_clk isp_hclk_gate = {
+ .name = "isp_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk veu_hclk_gate = {
+ .name = "veu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk bgm_hclk_gate = {
+ .name = "bgm_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x4000000,
+};
+static struct fh_clk adapt_hclk_gate = {
+ .name = "adapt_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x8000000,
+};
+static struct fh_clk jpg_hclk_gate = {
+ .name = "jpg_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk jpg_adapt_gate = {
+ .name = "jpg_adapt_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk vpu_hclk_gate = {
+ .name = "vpu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x40000000,
+};
+
+static struct fh_clk sdc0_clk_sample = {
+ .name = "sdc0_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf0000,
+};
+
+static struct fh_clk sdc0_clk_drv = {
+ .name = "sdc0_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00000,
+};
+
+static struct fh_clk sdc1_clk_sample = {
+ .name = "sdc1_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00,
+};
+
+static struct fh_clk sdc1_clk_drv = {
+ .name = "sdc1_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf000,
+};
+
+struct fh_clk *fh_clks[] = {
+ &osc_clk,
+ &pll_ddr_rclk,
+ &pll_cpu_pclk,
+ &pll_cpu_rclk,
+ &pll_sys_pclk,
+ &pll_sys_rclk,
+ &arm_clk,
+ &arc_clk,
+ &ahb_clk,
+ &ddr_clk,
+ &isp_aclk,
+ &ispb_aclk,
+ &jpeg_clk,
+ &jpeg_adapt_clk,
+ &vpu_clk,
+ &veu_clk,
+ &veu_adapt_clk,
+ &bgm_clk,
+ &mipi_dphy_clk,
+ &pllsysp_div12_clk,
+ &cis_clk_out,
+ &pix_clk,
+ &pts_clk,
+ &spi0_clk,
+ &spi1_clk,
+ &spi2_clk,
+ &sdc0_clk,
+ &sdc1_clk,
+ &uart0_clk,
+ &uart1_clk,
+ &uart2_clk,
+ &i2c0_clk,
+ &i2c1_clk,
+ &i2c2_clk,
+ &pwm_clk,
+ &wdt_clk,
+ &tmr0_clk,
+ &ac_clk,
+ &i2s_clk,
+ &sadc_clk,
+ &eth_clk,
+ &efuse_clk,
+ &gpio0_db_clk,
+ &gpio1_db_clk,
+ &mipi_wrap_gate,
+ &rtc_hclk_gate,
+ &emac_hclk_gate,
+ &usb_clk,
+ &aes_hclk_gate,
+ &ephy_clk_gate,
+ &sdc0_clk8x_gate,
+ &sdc1_clk8x_gate,
+ &gpio0_pclk_gate,
+ &gpio1_pclk_gate,
+ &mipic_pclk_gate,
+ &sdc0_clk_sample,
+ &sdc0_clk_drv,
+ &sdc1_clk_sample,
+ &sdc1_clk_drv,
+ &isp_hclk_gate,
+ &veu_hclk_gate,
+ &bgm_hclk_gate,
+ &adapt_hclk_gate,
+ &jpg_hclk_gate,
+ &jpg_adapt_gate,
+ &vpu_hclk_gate,
+ NULL,
+};
+EXPORT_SYMBOL(fh_clks);
diff --git a/arch/arm/mach-fh/fh8856v200/chip.h b/arch/arm/mach-fh/fh8856v200/chip.h
new file mode 100644
index 00000000..18ff2d65
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v200/chip.h
@@ -0,0 +1,421 @@
+#ifndef __ASM_ARCH_HL_H
+#define __ASM_ARCH_HL_H
+
+#include <linux/init.h>
+
+#define SRAM_GRANULARITY 32
+#define SRAM_SIZE (SZ_128K+SZ_8K)
+
+
+#define RAM_BASE (0x10000000)
+#define DDR_BASE (0xA0000000)
+
+
+#define PMU_REG_BASE (0xF0000000)
+#define TIMER_REG_BASE (0xF0C00000)
+#define GPIO0_REG_BASE (0xF0300000)
+#define GPIO1_REG_BASE (0xF4000000)
+#define UART0_REG_BASE (0xF0700000)
+#define UART1_REG_BASE (0xF0800000)
+#define SPI0_REG_BASE (0xF0500000)
+#define SPI1_REG_BASE (0xF0600000)
+#define SPI2_REG_BASE (0xF0640000)
+#define INTC_REG_BASE (0xE0200000)
+#define GMAC_REG_BASE (0xE0600000)
+#define USBC_REG_BASE (0xE0700000)
+#define DMAC_REG_BASE (0xE0300000)
+#define I2C1_REG_BASE (0xF0B00000)
+#define I2C0_REG_BASE (0xF0200000)
+#define I2C2_REG_BASE (0xF0100000)
+#define SDC0_REG_BASE (0xE2000000)
+#define SDC1_REG_BASE (0xE2200000)
+#define WDT_REG_BASE (0xF0D00000)
+#define PWM_REG_BASE (0xF0400000)
+#define I2S_REG_BASE (0xF0900000)
+#define ACW_REG_BASE (0xF0A00000)
+#define UART2_REG_BASE (0xF1300000)
+#define SADC_REG_BASE (0xF1200000)
+#define EFUSE_REG_BASE (0xF1600000)
+#define AES_REG_BASE (0xE8200000)
+#define RTC_REG_BASE (0xF1500000)
+#define DDRC_REG_BASE (0xED000000)
+#define CONSOLE_REG_BASE UART0_REG_BASE
+#define FH_UART_NUMBER 3
+
+#define FH_PMU_REG_SIZE 0x2110
+#define REG_PMU_CHIP_ID (0x0000)
+#define REG_PMU_IP_VER (0x0004)
+#define REG_PMU_FW_VER (0x0008)
+#define REG_PMU_CLK_SEL (0x000c)
+/*for HL REG_PMU_SYS_CTRL and CLK_SEL use one register */
+#define REG_PMU_SYS_CTRL (0x000c)
+#define REG_PMU_PLL0 (0x0010)
+#define REG_PMU_PLL1 (0x0014)
+#define REG_PMU_PLL0_CTRL (0x0018)
+#define REG_PMU_CLK_GATE (0x001c)
+#define REG_PMU_CLK_GATE1 (0x0020)
+#define REG_PMU_CLK_DIV0 (0x0024)
+#define REG_PMU_CLK_DIV1 (0x0028)
+#define REG_PMU_CLK_DIV2 (0x002c)
+#define REG_PMU_CLK_DIV3 (0x0030)
+#define REG_PMU_CLK_DIV4 (0x0034)
+#define REG_PMU_CLK_DIV5 (0x0038)
+#define REG_PMU_CLK_DIV6 (0x003c)
+#define REG_PMU_SWRST_MAIN_CTRL (0x0040)
+#define REG_PMU_SWRST_MAIN_CTRL2 (0x0044)
+#define REG_PMU_SWRST_AHB_CTRL (0x0048)
+#define REG_PMU_SWRST_APB_CTRL (0x004c)
+#define REG_PMU_SPC_IO_STATUS (0x0054)
+#define REG_PMU_SPC_FUN (0x0058)
+#define REG_PMU_CLK_DIV7 (0x005c)
+#define REG_PMU_CLK_DIV8 (0x0060)
+#define REG_PMU_PLL2 (0x0064)
+#define REG_PMU_PLL2_CTRL (0x0068)
+#define REG_PMU_PLL1_CTRL (0x006c)
+#define REG_PAD_PWR_SEL (0x0074)
+#define REG_PMU_SWRSTN_NSR (0x0078)
+#define REG_PMU_SWRSTN_NSR1 (0x007c)
+#define REG_PMU_ETHPHY_REG0 (0x2108)
+
+
+#define REG_PMU_PAD_BOOT_MODE_CFG (0x0080)
+#define REG_PMU_PAD_BOOT_SEL1_CFG (0x0084)
+#define REG_PMU_PAD_BOOT_SEL0_CFG (0x0088)
+#define REG_PMU_PAD_UART0_TX_CFG (0x008c)
+#define REG_PMU_PAD_UART0_RX_CFG (0x0090)
+#define REG_PMU_PAD_I2C0_SCL_CFG (0x0094)
+#define REG_PMU_PAD_I2C0_SDA_CFG (0x0098)
+#define REG_PMU_PAD_SENSOR_CLK_CFG (0x009c)
+#define REG_PMU_PAD_SENSOR_RSTN_CFG (0x00a0)
+#define REG_PMU_PAD_UART1_TX_CFG (0x00a4)
+#define REG_PMU_PAD_UART1_RX_CFG (0x00a8)
+#define REG_PMU_PAD_I2C1_SCL_CFG (0x00ac)
+#define REG_PMU_PAD_I2C1_SDA_CFG (0x00b0)
+#define REG_PMU_PAD_UART2_TX_CFG (0x00b4)
+#define REG_PMU_PAD_UART2_RX_CFG (0x00b8)
+#define REG_PMU_PAD_USB_PWREN_CFG (0x00bc)
+#define REG_PMU_PAD_PWM0_CFG (0x00c0)
+#define REG_PMU_PAD_PWM1_CFG (0x00c4)
+#define REG_PMU_PAD_PWM2_CFG (0x00c8)
+#define REG_PMU_PAD_PWM3_CFG (0x00cc)
+#define REG_PMU_PAD_MAC_RMII_CLK_CFG (0x00d0)
+#define REG_PMU_PAD_MAC_REF_CLK_CFG (0x00d4)
+#define REG_PMU_PAD_MAC_TXD0_CFG (0x00d8)
+#define REG_PMU_PAD_MAC_TXD1_CFG (0x00dc)
+#define REG_PMU_PAD_MAC_TXEN_CFG (0x00e0)
+#define REG_PMU_PAD_MAC_RXD0_CFG (0x00e4)
+#define REG_PMU_PAD_MAC_RXD1_CFG (0x00e8)
+#define REG_PMU_PAD_MAC_RXDV_CFG (0x00ec)
+#define REG_PMU_PAD_MAC_MDC_CFG (0x00f0)
+#define REG_PMU_PAD_MAC_MDIO_CFG (0x00f4)
+#define REG_PMU_PAD_SD1_CLK_CFG (0x00f8)
+#define REG_PMU_PAD_SD1_CD_CFG (0x00fc)
+#define REG_PMU_PAD_SD1_CMD_RSP_CFG (0x0100)
+#define REG_PMU_PAD_SD1_DATA_0_CFG (0x0104)
+#define REG_PMU_PAD_SD1_DATA_1_CFG (0x0108)
+#define REG_PMU_PAD_SD1_DATA_2_CFG (0x010c)
+#define REG_PMU_PAD_SD1_DATA_3_CFG (0x0110)
+#define REG_PMU_PAD_GPIO_0_CFG (0x0114)
+#define REG_PMU_PAD_GPIO_1_CFG (0x0118)
+#define REG_PMU_PAD_GPIO_2_CFG (0x011c)
+#define REG_PMU_PAD_GPIO_3_CFG (0x0120)
+#define REG_PMU_PAD_GPIO_4_CFG (0x0124)
+#define REG_PMU_PAD_SSI0_CLK_CFG (0x0128)
+#define REG_PMU_PAD_SSI0_CSN_0_CFG (0x012c)
+#define REG_PMU_PAD_SSI0_TXD_CFG (0x0130)
+#define REG_PMU_PAD_SSI0_RXD_CFG (0x0134)
+#define REG_PMU_PAD_SSI0_D2_CFG (0x0138)
+#define REG_PMU_PAD_SSI0_D3_CFG (0x013c)
+#define REG_PMU_PAD_SSI1_CLK_CFG (0x0140)
+#define REG_PMU_PAD_SSI1_CSN_0_CFG (0x0144)
+#define REG_PMU_PAD_SSI1_TXD_CFG (0x0148)
+#define REG_PMU_PAD_SSI1_RXD_CFG (0x014c)
+#define REG_PMU_PAD_SD0_CD_CFG (0x0150)
+#define REG_PMU_PAD_SD0_CLK_CFG (0x0154)
+#define REG_PMU_PAD_SD0_CMD_RSP_CFG (0x0158)
+#define REG_PMU_PAD_SD0_DATA_0_CFG (0x015c)
+#define REG_PMU_PAD_SD0_DATA_1_CFG (0x0160)
+#define REG_PMU_PAD_SD0_DATA_2_CFG (0x0164)
+#define REG_PMU_PAD_SD0_DATA_3_CFG (0x0168)
+#define REG_PMU_PAD_SADC_XAIN0_CFG (0x016c)
+#define REG_PMU_PAD_SADC_XAIN1_CFG (0x0170)
+#define REG_PMU_PAD_SADC_XAIN2_CFG (0x0174)
+#define REG_PMU_PAD_SADC_XAIN3_CFG (0x0178)
+#define REG_PMU_PAD_GPIO_28_CFG (0x017c)
+#define REG_PMU_PAD_GPIO_29_CFG (0x0180)
+
+#define REG_PMU_ARM_INT_0 (0x01e0)
+#define REG_PMU_ARM_INT_1 (0x01e4)
+#define REG_PMU_ARM_INT_2 (0x01e8)
+#define REG_PMU_A625_INT_0 (0x01ec)
+#define REG_PMU_A625_INT_1 (0x01f0)
+#define REG_PMU_A625_INT_2 (0x01f4)
+#define REG_PMU_DMA (0x01f8)
+#define REG_PMU_WDT_CTRL (0x01fc)
+#define REG_PMU_DBG_STAT0 (0x0200)
+#define REG_PMU_DBG_STAT1 (0x0204)
+#define REG_PMU_DBG_STAT2 (0x0208)
+#define REG_PMU_DBG_STAT3 (0x020c)
+#define REG_PMU_USB_SYS (0x0210)
+#define REG_PMU_USB_CFG (0x0214)
+#define REG_PMU_USB_TUNE (0x0218)
+#define REG_PMU_USB_SYS1 (0x0228)
+#define REG_PMU_PTSLO (0x022c)
+#define REG_PMU_PTSHI (0x0230)
+#define REG_PMU_USER0 (0x0234)
+#define REG_PMU_BOOT_MODE (0x0330)
+#define REG_PMU_DDR_SIZE (0x0334)
+#define REG_PMU_RESERVED2 (0x0338)
+#define REG_PMU_CHIP_INFO (0x033c)
+#define REG_PMU_EPHY_PARAM (0x0340)
+#define REG_PMU_RTC_PARAM (0x0344)
+#define REG_PMU_SD1_FUNC_SEL (0x03a0)
+#define REG_PMU_PRDCID_CTRL0 (0x0500)
+#define REG_PMU_A625BOOT0 (0x2000)
+#define REG_PMU_A625BOOT1 (0x2004)
+#define REG_PMU_A625BOOT2 (0x2008)
+#define REG_PMU_A625BOOT3 (0x200c)
+#define REG_PMU_A625_START_CTRL (0x2010)
+#define REG_PMU_ARC_INTC_MASK (0x2014)
+
+#define FH_GMAC_AHB_RESET (1<<17)
+#define FH_GMAC_SPEED_100M (1<<24)
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+#define PMU_RXDV_GPIO_SWITCH (REG_PMU_PAD_MAC_RXDV_CFG)
+#define PMU_RXDV_GPIO_MASK (0x0f000000)
+#define PMU_RXDV_GPIO_VAL (0x01000000)
+
+#define PMU_DWI2S_CLK_SEL_REG (REG_PMU_CLK_SEL)
+#define PMU_DWI2S_CLK_SEL_SHIFT (1)
+#define PMU_DWI2S_CLK_DIV_REG (REG_PMU_CLK_DIV6)
+#define PMU_DWI2S_CLK_DIV_SHIFT (0)
+
+/*ATTENTION: written by ARC */
+#define PMU_ARM_INT_MASK (0x01ec)
+#define PMU_ARM_INT_RAWSTAT (0x01f0)
+#define PMU_ARM_INT_STAT (0x01f4)
+
+#define PMU_A625_INT_MASK (0x01e0)
+#define PMU_A625_INT_RAWSTAT (0x01e4)
+#define PMU_A625_INT_STAT (0x01e8)
+
+#define PMU_IRQ 0
+#define DDRC_IRQ 1
+#define WDT_IRQ 2
+#define TMR0_IRQ 3
+#define VEU_IRQ 4
+#define PERF_IRQ 5
+#define VPU_IRQ 9
+#define I2C0_IRQ 11
+#define I2C1_IRQ 12
+#define JPEG_IRQ 13
+#define BGM_IRQ 14
+#define VEU_LOOP_IRQ 15
+#define AES_IRQ 16
+#define MIPIC_IRQ 17
+#define MIPI_WRAP_IRQ 18
+#define ACW_IRQ 19
+#define SADC_IRQ 20
+#define SPI1_IRQ 21
+#define JPEG_LOOP_IRQ 22
+#define DMAC0_IRQ 23
+#define DMAC1_IRQ 24
+#define I2S0_IRQ 25
+#define GPIO0_IRQ 26
+#define SPI0_IRQ 28
+#define ARC_SW_IRQ 29
+#define UART0_IRQ 30
+#define UART1_IRQ 31
+#define ARM_SW_IRQ 32
+#define RTC_IRQ 33
+#define PWM_IRQ 36
+#define SPI2_IRQ 38
+#define USBC_IRQ 39
+#define GPIO1_IRQ 40
+#define UART2_IRQ 41
+#define SDC0_IRQ 42
+#define SDC1_IRQ 43
+#define GMAC_IRQ 44
+#define EPHY_IRQ 45
+#define I2C2_IRQ 46
+#define RTC_ALM_IRQ 47
+#define RTC_CORE_IRQ 48
+/* because chips with some same function in different */
+/* pmu register, use wrap marco to make code to be same */
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+
+#define MEM_START_PHY_ADDR DDR_BASE
+#define MEM_SIZE 0x4000000
+
+
+#define NR_INTERNAL_IRQS (64)
+#define NR_EXTERNAL_IRQS (64)
+/*#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS)*/
+
+/* SWRST_MAIN_CTRL */
+#define CPU_RSTN_BIT (0)
+#define UTMI_RSTN_BIT (1)
+#define DDRPHY_RSTN_BIT (2)
+#define DDRC_RSTN_BIT (3)
+#define GPIO0_DB_RSTN_BIT (4)
+#define GPIO1_DB_RSTN_BIT (5)
+#define PIXEL_RSTN_BIT (6)
+#define PWM_RSTN_BIT (7)
+#define SPI0_RSTN_BIT (8)
+#define SPI1_RSTN_BIT (9)
+#define I2C0_RSTN_BIT (10)
+#define I2C1_RSTN_BIT (11)
+#define ACODEC_RSTN_BIT (12)
+#define I2S_RSTN_BIT (13)
+#define UART0_RSTN_BIT (14)
+#define UART1_RSTN_BIT (15)
+#define SADC_RSTN_BIT (16)
+#define ADAPT_RSTN_BIT (17)
+#define TMR_RSTN_BIT (18)
+#define UART2_RSTN_BIT (19)
+#define SPI2_RSTN_BIT (20)
+#define JPG_ADAPT_RSTN_BIT (21)
+#define ARC_RSTN_BIT (22)
+#define EFUSE_RSTN_BIT (23)
+#define JPG_RSTN_BIT (24)
+#define VEU_RSTN_BIT (25)
+#define VPU_RSTN_BIT (26)
+#define ISP_RSTN_BIT (27)
+#define BGM_RSTN_BIT (28)
+#define I2C2_RSTN_BIT (29)
+#define EPHY_RSTN_BIT (30)
+#define SYS_RSTN_BIT (31)
+
+/* SWRST_AHB_CTRL */
+#define EMC_HRSTN_BIT (0)
+#define SDC1_HRSTN_BIT (1)
+#define SDC0_HRSTN_BIT (2)
+#define AES_HRSTN_BIT (3)
+#define DMAC0_HRSTN_BIT (4)
+#define INTC_HRSTN_BIT (5)
+#define JPEG_ADAPT_HRSTN_BIT (7)
+#define JPEG_HRSTN_BIT (8)
+#define VCU_HRSTN_BIT (9)
+#define VPU_HRSTN_BIT (10)
+#define ISP_HRSTN_BIT (11)
+#define USB_HRSTN_BIT (12)
+#define HRSTN_BIT (13)
+#define EMAC_HRSTN_BIT (17)
+#define DDRC_HRSTN_BIT (19)
+#define DMAC1_HRSTN_BIT (20)
+#define BGM_HRSTN_BIT (22)
+#define ADAPT_HRSTN_BIT (23)
+
+/* SWRST_APB_CTRL */
+#define ACODEC_PRSTN_BIT (0)
+#define I2S_PRSTN_BIT (1)
+#define UART1_PRSTN_BIT (2)
+#define UART0_PRSTN_BIT (3)
+#define SPI0_PRSTN_BIT (4)
+#define SPI1_PRSTN_BIT (5)
+#define GPIO0_PRSTN_BIT (6)
+#define UART2_PRSTN_BIT (7)
+#define I2C2_PRSTN_BIT (8)
+#define I2C0_PRSTN_BIT (9)
+#define I2C1_PRSTN_BIT (10)
+#define TMR_PRSTN_BIT (11)
+#define PWM_PRSTN_BIT (12)
+#define MIPIW_PRSTN_BIT (13)
+#define MIPIC_PRSTN_BIT (14)
+#define RTC_PRSTN_BIT (15)
+#define SADC_PRSTN_BIT (16)
+#define EFUSE_PRSTN_BIT (17)
+#define SPI2_PRSTN_BIT (18)
+#define WDT_PRSTN_BIT (19)
+#define GPIO1_PRSTN_BIT (20)
+
+/* timer clk fpga 1M,soc 50M*/
+#ifdef CONFIG_FPGA
+#define TIMER_CLK (1000000)
+#else
+#define TIMER_CLK (50000000)
+#endif
+
+#define UART1_TX_HW_HANDSHAKE (9)
+#define UART1_RX_HW_HANDSHAKE (8)
+#define UART2_TX_HW_HANDSHAKE (13)
+#define UART2_RX_HW_HANDSHAKE (12)
+#define UART1_DMA_TX_CHAN (4)
+#define UART1_DMA_RX_CHAN (5)
+#define UART2_DMA_TX_CHAN (4)
+#define UART2_DMA_RX_CHAN (5)
+
+/*sdio*/
+#define SIMPLE_0 (0)
+#define SIMPLE_22 (1)
+#define SIMPLE_45 (2)
+#define SIMPLE_67 (3)
+#define SIMPLE_90 (4)
+#define SIMPLE_112 (5)
+#define SIMPLE_135 (6)
+#define SIMPLE_157 (7)
+#define SIMPLE_180 (8)
+#define SIMPLE_202 (9)
+#define SIMPLE_225 (10)
+#define SIMPLE_247 (11)
+#define SIMPLE_270 (12)
+#define SIMPLE_292 (13)
+#define SIMPLE_315 (14)
+#define SIMPLE_337 (15)
+
+
+
+#define SDIO0_RST_BIT (~UL(1<<2))
+#define SDIO0_CLK_RATE (50000000)
+#define SDIO0_CLK_DRV_SHIFT (20)
+#define SDIO0_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO0_CLK_SAM_SHIFT (16)
+#define SDIO0_CLK_SAM_DEGREE (SIMPLE_0)
+
+
+#define SDIO1_RST_BIT (~UL(1<<1))
+#define SDIO1_CLK_RATE (50000000)
+#define SDIO1_CLK_DRV_SHIFT (12)
+#define SDIO1_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO1_CLK_SAM_SHIFT (8)
+#define SDIO1_CLK_SAM_DEGREE (SIMPLE_0)
+
+#define SDC0_HRSTN (0x1<<2)
+#define SDC1_HRSTN (0x1<<1)
+#define SDC2_HRSTN (0)
+
+
+/*usb*/
+#define IRQ_UHOST USBC_IRQ
+#define FH_PA_OTG USBC_REG_BASE
+#define IRQ_OTG IRQ_UHOST
+#define FH_SZ_USBHOST SZ_1M
+#define FH_SZ_OTG SZ_1M
+
+#define USB_UTMI_RST_BIT (0x1<<1)
+#define USB_PHY_RST_BIT (0x11)
+#define USB_SLEEP_MODE_BIT (0x1<<24)
+#define USB_IDDQ_PWR_BIT (0x1<<10)
+
+
+/* Specific Uart Number */
+#define FH_UART_NUMBER 3
+#define CLK_SCAN_BIT_POS (28)
+#define INSIDE_PHY_ENABLE_BIT_POS (24)
+#define MAC_REF_CLK_DIV_MASK (0x0f)
+#define MAC_REF_CLK_DIV_BIT_POS (24)
+#define MAC_PAD_RMII_CLK_MASK (0x0f)
+#define MAC_PAD_RMII_CLK_BIT_POS (24)
+#define MAC_PAD_MAC_REF_CLK_BIT_POS (28)
+#define ETH_REF_CLK_OUT_GATE_BIT_POS (25)
+#define ETH_RMII_CLK_OUT_GATE_BIT_POS (28)
+#define IN_OR_OUT_PHY_SEL_BIT_POS (26)
+#define INSIDE_CLK_GATE_BIT_POS (0)
+#define INSIDE_PHY_SHUTDOWN_BIT_POS (31)
+#define INSIDE_PHY_RST_BIT_POS (30)
+#define INSIDE_PHY_TRAINING_BIT_POS (27)
+#define INSIDE_PHY_TRAINING_MASK (0x0f)
+
+#define TRAINING_EFUSE_ACTIVE_BIT_POS 4
+
+#endif /* __ASM_ARCH_HL_H */
diff --git a/arch/arm/mach-fh/fh8856v200/iopad.h b/arch/arm/mach-fh/fh8856v200/iopad.h
new file mode 100644
index 00000000..ebc24024
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v200/iopad.h
@@ -0,0 +1,729 @@
+#include <mach/pinctrl.h>
+#include <mach/pinctrl_osdep.h>
+#include <mach/board_config.h>
+
+/* PINCTRL_FUNC */
+PINCTRL_FUNC(GPIO30, 0, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO31, 1, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 1, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO32, 2, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 2, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 2, FUNC2, PUPD_UP, 0);
+PINCTRL_FUNC(UART0_TX, 3, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO33, 3, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART0_RX, 4, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO34, 4, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C0_SCL, 5, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO35, 5, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(I2C0_SDA, 6, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO36, 6, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(SENSOR_CLK, 7, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO12, 7, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO13, 8, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 9, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO39, 9, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 9, FUNC3, PUPD_NONE, 3);
+PINCTRL_FUNC(TEST_O_INT_RMII_CLK, 9, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 10, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO40, 10, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 10, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_0, 10, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 11, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO37, 11, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 11, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 11, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 11, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_1, 11, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 12, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO38, 12, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 12, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 12, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 12, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXEN, 12, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 13, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO41, 13, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM4, 13, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 13, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 13, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_0, 13, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 14, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO42, 14, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM5, 14, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 14, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 14, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_1, 14, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 15, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO47, 15, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 15, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_CRSDV, 15, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM0, 16, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO43, 16, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SCL, 16, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 16, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_0, 16, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM1, 17, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO44, 17, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SDA, 17, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 17, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_1, 17, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 18, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO45, 18, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 19, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO46, 19, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RMII_CLK, 20, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO48, 20, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 20, FUNC2, PUPD_NONE, 3);
+PINCTRL_FUNC(PWM2, 20, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_REF_CLK, 21, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(MAC_TXD_0, 22, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO49, 22, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 22, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM3, 22, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXD_1, 23, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO50, 23, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 23, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM4, 23, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXEN, 24, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO51, 24, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 24, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM5, 24, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_0, 25, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO52, 25, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 25, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM6, 25, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_1, 26, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO53, 26, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 26, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM7, 26, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXDV, 27, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO54, 27, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 27, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM8, 27, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 28, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO55, 28, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 28, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 29, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO56, 29, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 30, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO57, 30, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 30, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 31, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO58, 31, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 31, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO59, 32, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 32, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 33, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO60, 33, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 33, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 34, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO61, 34, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 34, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 35, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO62, 35, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 35, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 36, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO63, 36, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TRSTN, 37, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO0, 37, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DO, 37, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DO, 37, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CLK, 37, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CLK, 37, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADDAT, 37, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM6, 37, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDC, 37, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDO, 38, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO1, 38, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DI, 38, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DI, 38, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CSN_0, 38, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DADAT, 38, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM7, 38, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_I, 38, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDI, 39, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO2, 39, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_CLK, 39, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_CLK, 39, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_TXD, 39, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_TXD, 39, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADBCLK, 39, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM8, 39, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_O, 39, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TCK, 40, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO3, 40, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_WS, 40, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_WS, 40, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_RXD, 40, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_RXD, 40, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADLRC, 40, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 40, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDIO_I, 40, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TMS, 41, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO4, 41, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_MCLK, 41, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 41, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 41, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDC, 41, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI0_CLK, 42, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO5, 42, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CLK, 42, FUNC4, PUPD_NONE, 3);
+PINCTRL_FUNC(SSI0_CSN_0, 43, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO6, 43, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CMD_RSP, 43, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_TXD, 44, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO7, 44, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_0, 44, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_RXD, 45, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO8, 45, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_1, 45, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D2, 46, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO9, 46, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_TX, 46, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SCL, 46, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_2, 46, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D3, 47, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO10, 47, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_RX, 47, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SDA, 47, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_3, 47, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 48, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO11, 48, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CLK, 48, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 49, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CSN_0, 49, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 50, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO15, 50, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_TXD, 50, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 51, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO16, 51, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_RXD, 51, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CD, 52, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO17, 52, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARC_JTAG_TRSTN, 52, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(PAE_JTAG_TRSTN, 52, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD0_CLK, 53, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO18, 53, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 53, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDO, 53, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDO, 53, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CMD_RSP, 54, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO19, 54, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 54, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDI, 54, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDI, 54, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_0, 55, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO20, 55, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 55, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TCK, 55, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TCK, 55, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_1, 56, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO21, 56, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 56, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TMS, 56, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TMS, 56, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_2, 57, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO22, 57, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_TX, 57, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SCL, 57, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DABCLK, 57, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_3, 58, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO23, 58, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 58, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_RX, 58, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SDA, 58, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DALRC, 58, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SADC_XAIN0, 59, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO26, 59, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN1, 60, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO27, 60, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN2, 61, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO24, 61, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN3, 62, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO25, 62, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO28, 63, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 63, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM10, 63, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_DBG_CLK, 63, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 63, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXEN, 63, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 63, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO29, 64, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 64, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM11, 64, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(RTC_CLK, 64, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 64, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_OE, 64, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 64, FUNC7, PUPD_NONE, 0);
+
+
+/* PINCTRL_MUX */
+
+PINCTRL_MUX(AC_I2S_CLK, 0, &PAD39_AC_I2S_CLK);
+PINCTRL_MUX(AC_I2S_DI, 0, &PAD38_AC_I2S_DI);
+PINCTRL_MUX(AC_I2S_DO, 0, &PAD37_AC_I2S_DO);
+PINCTRL_MUX(AC_I2S_WS, 0, &PAD40_AC_I2S_WS);
+PINCTRL_MUX(AC_MCLK, 0, &PAD41_AC_MCLK);
+
+PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD55_ARC_JTAG_TCK);
+PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD54_ARC_JTAG_TDI);
+PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD53_ARC_JTAG_TDO);
+PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD56_ARC_JTAG_TMS);
+PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD52_ARC_JTAG_TRSTN);
+
+PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD40_ARM_JTAG_TCK);
+PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD39_ARM_JTAG_TDI);
+PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD38_ARM_JTAG_TDO);
+PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD41_ARM_JTAG_TMS);
+PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD37_ARM_JTAG_TRSTN);
+
+PINCTRL_MUX(DW_I2S_CLK, 0, &PAD39_DW_I2S_CLK);
+PINCTRL_MUX(DW_I2S_DI, 0, &PAD38_DW_I2S_DI);
+PINCTRL_MUX(DW_I2S_DO, 0, &PAD37_DW_I2S_DO);
+PINCTRL_MUX(DW_I2S_WS, 0, &PAD40_DW_I2S_WS);
+
+PINCTRL_MUX(ETH_LINK_ACT, 1, &PAD1_ETH_LINK_ACT,
+ &PAD63_ETH_LINK_ACT);
+PINCTRL_MUX(ETH_LINK_SPD, 1, &PAD2_ETH_LINK_SPD,
+ &PAD64_ETH_LINK_SPD);
+PINCTRL_MUX(ETH_LINK_STA, 1, &PAD2_ETH_LINK_STA,
+ &PAD64_ETH_LINK_STA);
+
+PINCTRL_MUX(I2C0_SCL, 0, &PAD5_I2C0_SCL);
+PINCTRL_MUX(I2C0_SDA, 0, &PAD6_I2C0_SDA);
+
+PINCTRL_MUX(I2C1_SCL, 2, &PAD11_I2C1_SCL, &PAD30_I2C1_SCL, &PAD46_I2C1_SCL);
+PINCTRL_MUX(I2C1_SDA, 2, &PAD12_I2C1_SDA, &PAD31_I2C1_SDA, &PAD47_I2C1_SDA);
+
+PINCTRL_MUX(I2C2_SCL, 1, &PAD16_I2C2_SCL, &PAD57_I2C2_SCL);
+PINCTRL_MUX(I2C2_SDA, 1, &PAD17_I2C2_SDA, &PAD58_I2C2_SDA);
+
+PINCTRL_MUX(MAC_MDC, 0, &PAD28_MAC_MDC, &PAD63_MAC_MDC);
+PINCTRL_MUX(MAC_MDIO, 0, &PAD29_MAC_MDIO, &PAD64_MAC_MDIO);
+PINCTRL_MUX(MAC_REF_CLK, 0, &PAD21_MAC_REF_CLK);
+PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD20_MAC_RMII_CLK);
+PINCTRL_MUX(MAC_RXDV, 0, &PAD27_MAC_RXDV);
+PINCTRL_MUX(MAC_RXD_0, 0, &PAD25_MAC_RXD_0);
+PINCTRL_MUX(MAC_RXD_1, 0, &PAD26_MAC_RXD_1);
+PINCTRL_MUX(MAC_TXD_0, 0, &PAD22_MAC_TXD_0);
+PINCTRL_MUX(MAC_TXD_1, 0, &PAD23_MAC_TXD_1);
+PINCTRL_MUX(MAC_TXEN, 0, &PAD24_MAC_TXEN);
+
+PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD55_PAE_JTAG_TCK);
+PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD54_PAE_JTAG_TDI);
+PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD53_PAE_JTAG_TDO);
+PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD56_PAE_JTAG_TMS);
+PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD52_PAE_JTAG_TRSTN);
+
+PINCTRL_MUX(PWM0, 0, &PAD16_PWM0);
+PINCTRL_MUX(PWM1, 0, &PAD17_PWM1);
+PINCTRL_MUX(PWM10, 0, &PAD63_PWM10);
+PINCTRL_MUX(PWM11, 0, &PAD64_PWM11);
+PINCTRL_MUX(PWM2, 0, &PAD11_PWM2, &PAD18_PWM2, &PAD20_PWM2);
+PINCTRL_MUX(PWM3, 0, &PAD12_PWM3, &PAD19_PWM3, &PAD22_PWM3);
+PINCTRL_MUX(PWM4, 0, &PAD13_PWM4, &PAD23_PWM4);
+PINCTRL_MUX(PWM5, 0, &PAD14_PWM5, &PAD24_PWM5);
+PINCTRL_MUX(PWM6, 1, &PAD25_PWM6, &PAD37_PWM6);
+PINCTRL_MUX(PWM7, 1, &PAD26_PWM7, &PAD38_PWM7);
+PINCTRL_MUX(PWM8, 1, &PAD27_PWM8, &PAD39_PWM8);
+PINCTRL_MUX(PWM9, 1, &PAD28_PWM9, &PAD40_PWM9);
+
+PINCTRL_MUX(RTC_CLK, 0, &PAD64_RTC_CLK);
+
+PINCTRL_MUX(SADC_XAIN0, 0, &PAD59_SADC_XAIN0);
+PINCTRL_MUX(SADC_XAIN1, 0, &PAD60_SADC_XAIN1);
+PINCTRL_MUX(SADC_XAIN2, 0, &PAD61_SADC_XAIN2);
+PINCTRL_MUX(SADC_XAIN3, 0, &PAD62_SADC_XAIN3);
+
+PINCTRL_MUX(SD0_CD, 0, &PAD52_SD0_CD);
+PINCTRL_MUX(SD0_CLK, 0, &PAD53_SD0_CLK);
+PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD54_SD0_CMD_RSP);
+PINCTRL_MUX(SD0_DATA_0, 0, &PAD55_SD0_DATA_0);
+PINCTRL_MUX(SD0_DATA_1, 0, &PAD56_SD0_DATA_1);
+PINCTRL_MUX(SD0_DATA_2, 0, &PAD57_SD0_DATA_2);
+PINCTRL_MUX(SD0_DATA_3, 0, &PAD58_SD0_DATA_3);
+
+PINCTRL_MUX(SD1_CD, 0, &PAD10_SD1_CD, &PAD22_SD1_CD, &PAD31_SD1_CD,
+ &PAD41_SD1_CD, &PAD63_SD1_CD);
+PINCTRL_MUX(SD1_CLK, 0, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP, 0, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0, 0, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1, 0, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2, 0, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3, 0, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+PINCTRL_MUX(SENSOR_CLK, 0, &PAD7_SENSOR_CLK);
+
+PINCTRL_MUX(SSI0_CLK, 0, &PAD42_SSI0_CLK);
+PINCTRL_MUX(SSI0_D2, 0, &PAD46_SSI0_D2);
+PINCTRL_MUX(SSI0_D3, 0, &PAD47_SSI0_D3);
+PINCTRL_MUX(SSI0_RXD, 0, &PAD45_SSI0_RXD);
+PINCTRL_MUX(SSI0_TXD, 0, &PAD44_SSI0_TXD);
+
+PINCTRL_MUX(SSI1_CLK, 2, &PAD11_SSI1_CLK, &PAD37_SSI1_CLK, &PAD48_SSI1_CLK,
+ &PAD53_SSI1_CLK);
+PINCTRL_MUX(SSI1_RXD, 2, &PAD14_SSI1_RXD, &PAD40_SSI1_RXD, &PAD51_SSI1_RXD,
+ &PAD55_SSI1_RXD);
+PINCTRL_MUX(SSI1_TXD, 2, &PAD13_SSI1_TXD, &PAD39_SSI1_TXD, &PAD50_SSI1_TXD,
+ &PAD54_SSI1_TXD);
+
+PINCTRL_MUX(SSI2_CLK, 1, &PAD37_SSI2_CLK, &PAD48_SSI2_CLK);
+PINCTRL_MUX(SSI2_CSN_0, 1, &PAD38_SSI2_CSN_0, &PAD49_SSI2_CSN_0);
+PINCTRL_MUX(SSI2_RXD, 1, &PAD40_SSI2_RXD, &PAD51_SSI2_RXD);
+PINCTRL_MUX(SSI2_TXD, 1, &PAD39_SSI2_TXD, &PAD50_SSI2_TXD);
+
+PINCTRL_MUX(UART0_RX, 0, &PAD4_UART0_RX);
+PINCTRL_MUX(UART0_TX, 0, &PAD3_UART0_TX);
+
+PINCTRL_MUX(UART1_RX, 0, &PAD10_UART1_RX, &PAD33_UART1_RX, &PAD47_UART1_RX);
+PINCTRL_MUX(UART1_TX, 0, &PAD9_UART1_TX, &PAD32_UART1_TX, &PAD46_UART1_TX);
+
+PINCTRL_MUX(UART2_RX, 0, &PAD14_UART2_RX, &PAD17_UART2_RX, &PAD35_UART2_RX,
+ &PAD58_UART2_RX);
+PINCTRL_MUX(UART2_TX, 0, &PAD13_UART2_TX, &PAD16_UART2_TX, &PAD34_UART2_TX,
+ &PAD57_UART2_TX);
+
+PINCTRL_MUX(USB_PWREN, 0, &PAD15_USB_PWREN, &PAD41_USB_PWREN);
+
+PINCTRL_MUX(GPIO0, 0, &PAD37_GPIO0);
+PINCTRL_MUX(GPIO1, 0, &PAD38_GPIO1);
+PINCTRL_MUX(GPIO2, 0, &PAD39_GPIO2);
+PINCTRL_MUX(GPIO3, 0, &PAD40_GPIO3);
+PINCTRL_MUX(GPIO4, 0, &PAD41_GPIO4);
+PINCTRL_MUX(GPIO5, 0, &PAD42_GPIO5);
+PINCTRL_MUX(GPIO6, 0, &PAD43_GPIO6);
+PINCTRL_MUX(GPIO7, 0, &PAD44_GPIO7);
+PINCTRL_MUX(GPIO8, 0, &PAD45_GPIO8);
+PINCTRL_MUX(GPIO9, 0, &PAD46_GPIO9);
+PINCTRL_MUX(GPIO10, 0, &PAD47_GPIO10);
+PINCTRL_MUX(GPIO11, 0, &PAD48_GPIO11);
+PINCTRL_MUX(GPIO12, 0, &PAD7_GPIO12);
+PINCTRL_MUX(GPIO13, 0, &PAD8_GPIO13);
+PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14);
+PINCTRL_MUX(GPIO15, 0, &PAD50_GPIO15);
+PINCTRL_MUX(GPIO16, 0, &PAD51_GPIO16);
+PINCTRL_MUX(GPIO17, 0, &PAD52_GPIO17);
+PINCTRL_MUX(GPIO18, 0, &PAD53_GPIO18);
+PINCTRL_MUX(GPIO19, 0, &PAD54_GPIO19);
+PINCTRL_MUX(GPIO20, 0, &PAD55_GPIO20);
+PINCTRL_MUX(GPIO21, 0, &PAD56_GPIO21);
+PINCTRL_MUX(GPIO22, 0, &PAD57_GPIO22);
+PINCTRL_MUX(GPIO23, 0, &PAD58_GPIO23);
+PINCTRL_MUX(GPIO24, 0, &PAD61_GPIO24);
+PINCTRL_MUX(GPIO25, 0, &PAD62_GPIO25);
+PINCTRL_MUX(GPIO26, 0, &PAD59_GPIO26);
+PINCTRL_MUX(GPIO27, 0, &PAD60_GPIO27);
+PINCTRL_MUX(GPIO28, 0, &PAD63_GPIO28);
+PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29);
+PINCTRL_MUX(GPIO30, 0, &PAD0_GPIO30);
+PINCTRL_MUX(GPIO31, 0, &PAD1_GPIO31);
+PINCTRL_MUX(GPIO32, 0, &PAD2_GPIO32);
+PINCTRL_MUX(GPIO33, 0, &PAD3_GPIO33);
+PINCTRL_MUX(GPIO34, 0, &PAD4_GPIO34);
+PINCTRL_MUX(GPIO35, 0, &PAD5_GPIO35);
+PINCTRL_MUX(GPIO36, 0, &PAD6_GPIO36);
+PINCTRL_MUX(GPIO37, 0, &PAD11_GPIO37);
+PINCTRL_MUX(GPIO38, 0, &PAD12_GPIO38);
+PINCTRL_MUX(GPIO39, 0, &PAD9_GPIO39);
+PINCTRL_MUX(GPIO40, 0, &PAD10_GPIO40);
+PINCTRL_MUX(GPIO41, 0, &PAD13_GPIO41);
+PINCTRL_MUX(GPIO42, 0, &PAD14_GPIO42);
+PINCTRL_MUX(GPIO43, 0, &PAD16_GPIO43);
+PINCTRL_MUX(GPIO44, 0, &PAD17_GPIO44);
+PINCTRL_MUX(GPIO45, 0, &PAD18_GPIO45);
+PINCTRL_MUX(GPIO46, 0, &PAD19_GPIO46);
+PINCTRL_MUX(GPIO47, 0, &PAD15_GPIO47);
+PINCTRL_MUX(GPIO48, 0, &PAD20_GPIO48);
+PINCTRL_MUX(GPIO49, 0, &PAD22_GPIO49);
+PINCTRL_MUX(GPIO50, 0, &PAD23_GPIO50);
+PINCTRL_MUX(GPIO51, 0, &PAD24_GPIO51);
+PINCTRL_MUX(GPIO52, 0, &PAD25_GPIO52);
+PINCTRL_MUX(GPIO53, 0, &PAD26_GPIO53);
+PINCTRL_MUX(GPIO54, 0, &PAD27_GPIO54);
+PINCTRL_MUX(GPIO55, 0, &PAD28_GPIO55);
+PINCTRL_MUX(GPIO56, 0, &PAD29_GPIO56);
+PINCTRL_MUX(GPIO57, 0, &PAD30_GPIO57);
+PINCTRL_MUX(GPIO58, 0, &PAD31_GPIO58);
+PINCTRL_MUX(GPIO59, 0, &PAD32_GPIO59);
+PINCTRL_MUX(GPIO60, 0, &PAD33_GPIO60);
+PINCTRL_MUX(GPIO61, 0, &PAD34_GPIO61);
+PINCTRL_MUX(GPIO62, 0, &PAD35_GPIO62);
+PINCTRL_MUX(GPIO63, 0, &PAD36_GPIO63);
+
+PINCTRL_MUX(SD1_CLK_EMMC, 3, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP_EMMC, 3, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0_EMMC, 3, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1_EMMC, 3, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2_EMMC, 3, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3_EMMC, 3, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+/* PINCTRL_DEVICE */
+PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO,
+ &MUX_AC_I2S_WS, &MUX_AC_MCLK);
+PINCTRL_DEVICE(AC_MCLK, 1, &MUX_AC_MCLK);
+PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI,
+ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN);
+PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI,
+ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN);
+PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO,
+ &MUX_DW_I2S_WS);
+PINCTRL_DEVICE(ETH, 2, &MUX_ETH_LINK_ACT, &MUX_ETH_LINK_STA);
+PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA);
+PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA);
+PINCTRL_DEVICE(I2C2, 2, &MUX_I2C2_SCL, &MUX_I2C2_SDA);
+PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI,
+ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN);
+PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0);
+PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1);
+PINCTRL_DEVICE(PWM10, 1, &MUX_PWM10);
+PINCTRL_DEVICE(PWM11, 1, &MUX_PWM11);
+PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2);
+PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3);
+PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4);
+PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5);
+PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6);
+PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7);
+PINCTRL_DEVICE(PWM8, 1, &MUX_PWM8);
+PINCTRL_DEVICE(PWM9, 1, &MUX_PWM9);
+PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK,
+ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1,
+ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN);
+PINCTRL_DEVICE(RTC, 1, &MUX_RTC_CLK);
+PINCTRL_DEVICE(SADC_XAIN0, 1, &MUX_SADC_XAIN0);
+PINCTRL_DEVICE(SADC_XAIN1, 1, &MUX_SADC_XAIN1);
+PINCTRL_DEVICE(SADC_XAIN2, 1, &MUX_SADC_XAIN2);
+PINCTRL_DEVICE(SADC_XAIN3, 1, &MUX_SADC_XAIN3);
+PINCTRL_DEVICE(SD0, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0);
+PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_WIFI, 6, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, &MUX_SD0_DATA_0,
+ &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD1, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_1BIT_NO_WP, 4, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0);
+PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_WIFI, 6, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, &MUX_SD1_DATA_0,
+ &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SENSOR_CLK, 1, &MUX_SENSOR_CLK);
+PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_RXD,
+ &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_D2,
+ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI1, 4, &MUX_GPIO14, &MUX_SSI1_CLK, &MUX_SSI1_RXD,
+ &MUX_SSI1_TXD);
+PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN_0, &MUX_SSI2_RXD,
+ &MUX_SSI2_TXD);
+PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX);
+PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX);
+PINCTRL_DEVICE(UART2, 2, &MUX_UART2_RX, &MUX_UART2_TX);
+PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN);
+PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0);
+PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1);
+PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2);
+PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3);
+PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4);
+PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5);
+PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6);
+PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7);
+PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8);
+PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9);
+PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10);
+PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11);
+PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12);
+PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13);
+PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14);
+PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15);
+PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16);
+PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17);
+PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18);
+PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19);
+PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20);
+PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21);
+PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22);
+PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23);
+PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24);
+PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25);
+PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26);
+PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27);
+PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28);
+PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29);
+PINCTRL_DEVICE(GPIO30, 1, &MUX_GPIO30);
+PINCTRL_DEVICE(GPIO31, 1, &MUX_GPIO31);
+PINCTRL_DEVICE(GPIO32, 1, &MUX_GPIO32);
+PINCTRL_DEVICE(GPIO33, 1, &MUX_GPIO33);
+PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34);
+PINCTRL_DEVICE(GPIO35, 1, &MUX_GPIO35);
+PINCTRL_DEVICE(GPIO36, 1, &MUX_GPIO36);
+PINCTRL_DEVICE(GPIO37, 1, &MUX_GPIO37);
+PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38);
+PINCTRL_DEVICE(GPIO39, 1, &MUX_GPIO39);
+PINCTRL_DEVICE(GPIO40, 1, &MUX_GPIO40);
+PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41);
+PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42);
+PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43);
+PINCTRL_DEVICE(GPIO44, 1, &MUX_GPIO44);
+PINCTRL_DEVICE(GPIO45, 1, &MUX_GPIO45);
+PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46);
+PINCTRL_DEVICE(GPIO47, 1, &MUX_GPIO47);
+PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48);
+PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49);
+PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50);
+PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51);
+PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52);
+PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53);
+PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54);
+PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55);
+PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56);
+PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57);
+PINCTRL_DEVICE(GPIO58, 1, &MUX_GPIO58);
+PINCTRL_DEVICE(GPIO59, 1, &MUX_GPIO59);
+PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60);
+PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61);
+PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62);
+PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63);
+
+PINCTRL_DEVICE(SD1_EMMC, 6, &MUX_SD1_CLK_EMMC, &MUX_SD1_CMD_RSP_EMMC,
+ &MUX_SD1_DATA_0_EMMC, &MUX_SD1_DATA_1_EMMC, &MUX_SD1_DATA_2_EMMC,
+ &MUX_SD1_DATA_3_EMMC);
+
+void fh_pinctrl_init_devicelist(OS_LIST *list)
+{
+ OS_LIST_EMPTY(list);
+
+ /*PINCTRL_ADD_DEVICE*/
+ PINCTRL_ADD_DEVICE(ACI2S);
+ PINCTRL_ADD_DEVICE(AC_MCLK);
+ PINCTRL_ADD_DEVICE(ARCJTAG);
+ PINCTRL_ADD_DEVICE(ARMJTAG);
+ PINCTRL_ADD_DEVICE(DWI2S);
+ PINCTRL_ADD_DEVICE(ETH);
+ PINCTRL_ADD_DEVICE(I2C0);
+ PINCTRL_ADD_DEVICE(I2C1);
+ PINCTRL_ADD_DEVICE(I2C2);
+ PINCTRL_ADD_DEVICE(PAEJTAG);
+ PINCTRL_ADD_DEVICE(PWM0);
+ PINCTRL_ADD_DEVICE(PWM1);
+ PINCTRL_ADD_DEVICE(PWM10);
+ PINCTRL_ADD_DEVICE(PWM11);
+ PINCTRL_ADD_DEVICE(PWM2);
+ PINCTRL_ADD_DEVICE(PWM3);
+ PINCTRL_ADD_DEVICE(PWM4);
+ PINCTRL_ADD_DEVICE(PWM5);
+ PINCTRL_ADD_DEVICE(PWM6);
+ PINCTRL_ADD_DEVICE(PWM7);
+ PINCTRL_ADD_DEVICE(PWM8);
+ PINCTRL_ADD_DEVICE(PWM9);
+ PINCTRL_ADD_DEVICE(RMII);
+ PINCTRL_ADD_DEVICE(RTC);
+ PINCTRL_ADD_DEVICE(SADC_XAIN0);
+ PINCTRL_ADD_DEVICE(SADC_XAIN1);
+ PINCTRL_ADD_DEVICE(SADC_XAIN2);
+ PINCTRL_ADD_DEVICE(SADC_XAIN3);
+ PINCTRL_ADD_DEVICE(SD0);
+ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_WIFI);
+ PINCTRL_ADD_DEVICE(SD1);
+ PINCTRL_ADD_DEVICE(SD1_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_WIFI);
+ PINCTRL_ADD_DEVICE(SENSOR_CLK);
+ PINCTRL_ADD_DEVICE(SSI0);
+ PINCTRL_ADD_DEVICE(SSI0_4BIT);
+ PINCTRL_ADD_DEVICE(SSI1);
+ PINCTRL_ADD_DEVICE(SSI2);
+ PINCTRL_ADD_DEVICE(UART0);
+ PINCTRL_ADD_DEVICE(UART1);
+ PINCTRL_ADD_DEVICE(UART2);
+ PINCTRL_ADD_DEVICE(USB);
+ PINCTRL_ADD_DEVICE(GPIO0);
+ PINCTRL_ADD_DEVICE(GPIO1);
+ PINCTRL_ADD_DEVICE(GPIO2);
+ PINCTRL_ADD_DEVICE(GPIO3);
+ PINCTRL_ADD_DEVICE(GPIO4);
+ PINCTRL_ADD_DEVICE(GPIO5);
+ PINCTRL_ADD_DEVICE(GPIO6);
+ PINCTRL_ADD_DEVICE(GPIO7);
+ PINCTRL_ADD_DEVICE(GPIO8);
+ PINCTRL_ADD_DEVICE(GPIO9);
+ PINCTRL_ADD_DEVICE(GPIO10);
+ PINCTRL_ADD_DEVICE(GPIO11);
+ PINCTRL_ADD_DEVICE(GPIO12);
+ PINCTRL_ADD_DEVICE(GPIO13);
+ PINCTRL_ADD_DEVICE(GPIO14);
+ PINCTRL_ADD_DEVICE(GPIO15);
+ PINCTRL_ADD_DEVICE(GPIO16);
+ PINCTRL_ADD_DEVICE(GPIO17);
+ PINCTRL_ADD_DEVICE(GPIO18);
+ PINCTRL_ADD_DEVICE(GPIO19);
+ PINCTRL_ADD_DEVICE(GPIO20);
+ PINCTRL_ADD_DEVICE(GPIO21);
+ PINCTRL_ADD_DEVICE(GPIO22);
+ PINCTRL_ADD_DEVICE(GPIO23);
+ PINCTRL_ADD_DEVICE(GPIO24);
+ PINCTRL_ADD_DEVICE(GPIO25);
+ PINCTRL_ADD_DEVICE(GPIO26);
+ PINCTRL_ADD_DEVICE(GPIO27);
+ PINCTRL_ADD_DEVICE(GPIO28);
+ PINCTRL_ADD_DEVICE(GPIO29);
+ PINCTRL_ADD_DEVICE(GPIO30);
+ PINCTRL_ADD_DEVICE(GPIO31);
+ PINCTRL_ADD_DEVICE(GPIO32);
+ PINCTRL_ADD_DEVICE(GPIO33);
+ PINCTRL_ADD_DEVICE(GPIO34);
+ PINCTRL_ADD_DEVICE(GPIO35);
+ PINCTRL_ADD_DEVICE(GPIO36);
+ PINCTRL_ADD_DEVICE(GPIO37);
+ PINCTRL_ADD_DEVICE(GPIO38);
+ PINCTRL_ADD_DEVICE(GPIO39);
+ PINCTRL_ADD_DEVICE(GPIO40);
+ PINCTRL_ADD_DEVICE(GPIO41);
+ PINCTRL_ADD_DEVICE(GPIO42);
+ PINCTRL_ADD_DEVICE(GPIO43);
+ PINCTRL_ADD_DEVICE(GPIO44);
+ PINCTRL_ADD_DEVICE(GPIO45);
+ PINCTRL_ADD_DEVICE(GPIO46);
+ PINCTRL_ADD_DEVICE(GPIO47);
+ PINCTRL_ADD_DEVICE(GPIO48);
+ PINCTRL_ADD_DEVICE(GPIO49);
+ PINCTRL_ADD_DEVICE(GPIO50);
+ PINCTRL_ADD_DEVICE(GPIO51);
+ PINCTRL_ADD_DEVICE(GPIO52);
+ PINCTRL_ADD_DEVICE(GPIO53);
+ PINCTRL_ADD_DEVICE(GPIO54);
+ PINCTRL_ADD_DEVICE(GPIO55);
+ PINCTRL_ADD_DEVICE(GPIO56);
+ PINCTRL_ADD_DEVICE(GPIO57);
+ PINCTRL_ADD_DEVICE(GPIO58);
+ PINCTRL_ADD_DEVICE(GPIO59);
+ PINCTRL_ADD_DEVICE(GPIO60);
+ PINCTRL_ADD_DEVICE(GPIO61);
+ PINCTRL_ADD_DEVICE(GPIO62);
+ PINCTRL_ADD_DEVICE(GPIO63);
+
+ PINCTRL_ADD_DEVICE(SD1_EMMC);
+}
+
+char *fh_pinctrl_selected_devices[] =
+{
+ CONFIG_PINCTRL_SELECT
+};
diff --git a/arch/arm/mach-fh/fh8856v210/Makefile b/arch/arm/mach-fh/fh8856v210/Makefile
new file mode 100644
index 00000000..1443fdae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v210/Makefile
@@ -0,0 +1 @@
+obj-y += board.o chip.o
\ No newline at end of file
diff --git a/arch/arm/mach-fh/fh8856v210/board.c b/arch/arm/mach-fh/fh8856v210/board.c
new file mode 100644
index 00000000..9fc938c1
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v210/board.c
@@ -0,0 +1,1165 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/phy.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/eeprom.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/if_alg.h>
+#include <linux/mmc/host.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/io.h>
+#include <mach/board_config.h>
+#include <mach/pinctrl.h>
+#include <mach/clock.h>
+#include <mach/fh_uart_plat.h>
+#include <mach/fh_mci_plat.h>
+#include <mach/fh_gmac_plat.h>
+#include <mach/fh_gpio_plat.h>
+#include <mach/fh_efuse_plat.h>
+#include <mach/fh_dma_plat.h>
+#include <mach/fh_spi_plat.h>
+#include <mach/fh_i2s_plat.h>
+#include <mach/fh_pwm_plat.h>
+#include <mach/fh_wdt_plat.h>
+#include <mach/fh_usb_plat.h>
+#include <mach/fh_sadc_plat.h>
+#include <mach/fh_rtc_plat.h>
+#include "chip.h"
+
+struct uart_port fh_serial_ports[FH_UART_NUMBER];
+
+static struct map_desc fh8856v210_io_desc[] = {
+ {
+ .virtual = VA_RAM_REG_BASE,
+ .pfn = __phys_to_pfn(RAM_BASE),
+ .length = SZ_16K,
+ .type = MT_MEMORY_RWX,
+ },
+ {
+ .virtual = VA_DDRC_REG_BASE,
+ .pfn = __phys_to_pfn(DDRC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_INTC_REG_BASE,
+ .pfn = __phys_to_pfn(INTC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_TIMER_REG_BASE,
+ .pfn = __phys_to_pfn(TIMER_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_PMU_REG_BASE,
+ .pfn = __phys_to_pfn(PMU_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART0_REG_BASE,
+ .pfn = __phys_to_pfn(UART0_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART1_REG_BASE,
+ .pfn = __phys_to_pfn(UART1_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART2_REG_BASE,
+ .pfn = __phys_to_pfn(UART2_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+
+};
+
+static struct resource fh_gpio0_resources[] = {
+ {
+ .start = GPIO0_REG_BASE,
+ .end = GPIO0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO0_IRQ,
+ .end = GPIO0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gpio1_resources[] = {
+ {
+ .start = GPIO1_REG_BASE,
+ .end = GPIO1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO1_IRQ,
+ .end = GPIO1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart0_resources[] = {
+ {
+ .start = (UART0_REG_BASE),
+ .end = (UART0_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = UART0_IRQ,
+ .end = UART0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart1_resources[] = {
+ {
+ .start = (UART1_REG_BASE),
+ .end = (UART1_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART1_IRQ,
+ .end = UART1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_uart2_resources[] = {
+ {
+ .start = (UART2_REG_BASE),
+ .end = (UART2_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART2_IRQ,
+ .end = UART2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+static struct resource fh_sdc0_resources[] = {
+ {
+ .start = SDC0_REG_BASE,
+ .end = SDC0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC0_IRQ,
+ .end = SDC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_sdc1_resources[] = {
+ {
+ .start = SDC1_REG_BASE,
+ .end = SDC1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC1_IRQ,
+ .end = SDC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gmac_resources[] = {
+ {
+ .start = GMAC_REG_BASE,
+ .end = GMAC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GMAC_IRQ,
+ .end = GMAC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource fh_wdt_resources[] = {
+ {
+ .start = WDT_REG_BASE,
+ .end = WDT_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = WDT_IRQ,
+ .end = WDT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct resource fh_perf_resources[] = {
+ {
+ .start = PMU_REG_BASE,
+ .end = PMU_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PERF_IRQ,
+ .end = PERF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+
+static struct fh_gmac_platform_data fh_gmac_data = {
+ .phy_reset_pin = 29,
+};
+
+static struct fh_uart_dma uart1_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART1_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART1_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART1_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART1_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+static struct fh_uart_dma uart2_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART2_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART2_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART2_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART2_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+
+static struct fh_platform_uart fh_uart_platform_data[] = {
+ {
+ .mapbase = UART0_REG_BASE,
+ .fifo_size = 16,
+ .irq = UART0_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = NULL,
+ },
+ {
+ .mapbase = UART1_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART1_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart1_dma_info,
+ },
+ {
+ .mapbase = UART2_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART2_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart2_dma_info,
+ },
+};
+
+static struct resource fh_pwm_resources[] = {
+ {
+ .start = PWM_REG_BASE,
+ .end = PWM_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PWM_IRQ,
+ .end = PWM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_i2c_resources_0[] = {
+ {
+ .start = I2C0_REG_BASE,
+ .end = I2C0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C0_IRQ,
+ .end = I2C0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_1[] = {
+ {
+ .start = I2C1_REG_BASE,
+ .end = I2C1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C1_IRQ,
+ .end = I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_2[] = {
+ {
+ .start = I2C2_REG_BASE,
+ .end = I2C2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C2_IRQ,
+ .end = I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_rtc_resources[] = {
+ {
+ .start = RTC_REG_BASE,
+ .end = RTC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio0_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO0",
+ .base = 0,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio1_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO1",
+ .base = 32,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_pwm_data pwm_data = {
+ .npwm = 12,
+};
+
+static struct resource fh_sadc_resources[] = {
+ {
+ .start = SADC_REG_BASE,
+ .end = SADC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SADC_IRQ,
+ .end = SADC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_aes_resources[] = {
+ {
+ .start = AES_REG_BASE,
+ .end = AES_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = AES_IRQ,
+ .end = AES_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_efuse_resources[] = {
+ {
+ .start = EFUSE_REG_BASE,
+ .end = EFUSE_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct resource fh_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+static struct resource fh_axi_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+static struct resource fh_spi0_resources[] = {
+ {
+ .start = SPI0_REG_BASE,
+ .end = SPI0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI0_IRQ,
+ .end = SPI0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi1_resources[] = {
+ {
+ .start = SPI1_REG_BASE,
+ .end = SPI1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI1_IRQ,
+ .end = SPI1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi2_resources[] = {
+ {
+ .start = SPI2_REG_BASE,
+ .end = SPI2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "fh spi2 mem",
+ },
+ {
+ .start = SPI2_IRQ,
+ .end = SPI2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ .name = "fh spi2 irq",
+ },
+};
+
+static struct resource fh_usb_resources[] = {
+ {
+ .start = USBC_REG_BASE,
+ .end = USBC_REG_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USBC_IRQ,
+ .end = USBC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static unsigned int fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+
+struct fh_mci_board fh_mci = {
+ .num_slots = 1,
+ .get_cd = fh_mci_sys_card_detect_fixed,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+ .rescan_max_num = 2,
+};
+
+struct fh_mci_board fh_mci_sd = {
+ .num_slots = 1,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+};
+
+static struct platform_device fh_gmac_device = {
+ .name = "fh_gmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gmac_resources),
+ .resource = fh_gmac_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_gmac_data,
+ },
+};
+
+struct platform_device fh_sd0_device = {
+ .name = "fh_mci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sdc0_resources),
+ .resource = fh_sdc0_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci_sd,
+ }
+};
+
+struct platform_device fh_sd1_device = {
+ .name = "fh_mci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_sdc1_resources),
+ .resource = fh_sdc1_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci,
+ }
+};
+
+struct fh_sadc_platform_data fh_sadc_data = {
+ .ref_vol = 1800,
+ .active_bit = 0xfff,
+};
+
+static struct platform_device fh_sadc_device = {
+ .name = "fh_sadc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sadc_resources),
+ .resource = fh_sadc_resources,
+ .dev = {
+ .platform_data = &fh_sadc_data,
+ },
+};
+
+static struct platform_device fh_uart0_device = {
+ .name = "ttyS",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_uart0_resources),
+ .resource = fh_uart0_resources,
+ .dev.platform_data = &fh_uart_platform_data[0],
+};
+
+static struct platform_device fh_uart1_device = {
+ .name = "ttyS",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_uart1_resources),
+ .resource = fh_uart1_resources,
+ .dev.platform_data = &fh_uart_platform_data[1],
+};
+
+static struct platform_device fh_uart2_device = {
+ .name = "ttyS",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_uart2_resources),
+ .resource = fh_uart2_resources,
+ .dev.platform_data = &fh_uart_platform_data[2],
+};
+
+static struct platform_device fh_pinctrl_device = {
+ .name = "fh_pinctrl",
+ .id = 0,
+};
+
+static struct platform_device fh_i2c0_device = {
+ .name = "fh_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_0),
+ .resource = fh_i2c_resources_0,
+};
+
+static struct platform_device fh_i2c1_device = {
+ .name = "fh_i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_1),
+ .resource = fh_i2c_resources_1,
+};
+
+static struct platform_device fh_i2c2_device = {
+ .name = "fh_i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_2),
+ .resource = fh_i2c_resources_2,
+};
+
+static struct fh_rtc_plat_data rtc_plat_data[] = {
+ {
+ .lut_cof = 58,
+ .lut_offset = 0xff,
+ .tsensor_cp_default_out = 0x993,
+ .clk_name = "rtc_hclk_gate",
+ },
+ {
+ .lut_cof = 71,
+ .lut_offset = 0xf6,
+ .tsensor_cp_default_out = 0x9cc,
+ .clk_name = "rtc_hclk_gate",
+ }
+};
+
+static struct platform_device fh_rtc_device = {
+ .name = "fh_rtc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_rtc_resources),
+ .resource = fh_rtc_resources,
+ .dev.platform_data = &rtc_plat_data[0],
+};
+
+static struct resource fh_i2s_resources[] = {
+ {
+ .start = I2S_REG_BASE,
+ .end = I2S_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ACW_REG_BASE,
+ .end = ACW_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = I2S0_IRQ,
+ .end = I2S0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_i2s_platform_data fh_i2s_data = {
+ .dma_capture_channel = 4,
+ .dma_playback_channel = 5,
+ .dma_master = 0,
+ .dma_rx_hs_num = 10,
+ .dma_tx_hs_num = 11,
+ .clk = "i2s_clk",
+ .acodec_mclk = "ac_clk",
+};
+
+static struct platform_device fh_i2s_device = {
+ .name = "fh_audio",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2s_resources),
+ .resource = fh_i2s_resources,
+ .dev = {
+ .platform_data = &fh_i2s_data,
+ },
+};
+
+static struct platform_device fh_gpio0_device = {
+ .name = GPIO_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gpio0_resources),
+ .resource = fh_gpio0_resources,
+ .dev = {
+ .platform_data = &fh_gpio0_chip,
+ },
+};
+
+static struct platform_device fh_gpio1_device = {
+ .name = GPIO_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_gpio1_resources),
+ .resource = fh_gpio1_resources,
+ .dev = {
+ .platform_data = &fh_gpio1_chip,
+ },
+};
+
+static struct platform_device fh_aes_device = {
+ .name = "fh_aes",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_aes_resources),
+ .resource = fh_aes_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+struct fh_efuse_platform_data fh_efuse_plat_data = {
+ .efuse_support_flag = CRYPTO_CPU_SET_KEY |
+ CRYPTO_EX_MEM_SET_KEY |
+ CRYPTO_EX_MEM_SWITCH_KEY |
+ CRYPTO_EX_MEM_4_ENTRY_1_KEY |
+ CRYPTO_EX_MEM_INDEP_POWER,
+};
+
+
+
+#define FH_SPI0_CS0 (6)
+#define FH_SPI0_CS1 (55)
+
+#define FH_SPI1_CS0 (14)
+#define FH_SPI1_CS1 (57)
+
+#define SPI0_FIFO_DEPTH (128)
+#define SPI0_CLK_IN (200000000)
+#define SPI0_MAX_SLAVE_NO (2)
+#define SPI0_DMA_RX_CHANNEL (0)
+#define SPI0_DMA_TX_CHANNEL (1)
+
+#define SPI1_FIFO_DEPTH (64)
+#define SPI1_CLK_IN (100000000)
+#define SPI1_MAX_SLAVE_NO (2)
+#define SPI1_DMA_RX_CHANNEL (2)
+#define SPI1_DMA_TX_CHANNEL (3)
+
+#define SPI2_CLK_IN (100000000)
+
+/* SPI_TRANSFER_USE_DMA */
+static struct fh_spi_platform_data fh_spi0_data = {
+ .bus_no = 0,
+ .apb_clock_in = SPI0_CLK_IN,
+ .clock_source = {100000000, 150000000, 200000000},
+ .clock_source_num = 3,
+ .slave_max_num = SPI0_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI0_CS0,
+ .cs_data[0].name = "spi0_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI0_CS1,
+ .cs_data[1].name = "spi0_cs1",
+ .clk_name = "spi0_clk",
+ .dma_transfer_enable = SPI_TRANSFER_USE_DMA,
+ .rx_dma_channel = SPI0_DMA_RX_CHANNEL,
+ .rx_handshake_num = 4,
+ /*dma use inc mode could move data by burst mode...*/
+ /*or move data use single mode with low efficient*/
+ .ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |
+ MULTI_WIRE_SUPPORT,
+};
+
+static struct fh_spi_platform_data fh_spi1_data = {
+ .bus_no = 1,
+ .apb_clock_in = SPI1_CLK_IN,
+ .clock_source = {SPI1_CLK_IN},
+ .clock_source_num = 1,
+ .slave_max_num = SPI1_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI1_CS0,
+ .cs_data[0].name = "spi1_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI1_CS1,
+ .cs_data[1].name = "spi1_cs1",
+ .clk_name = "spi1_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct fh_spi_platform_data fh_spi2_data = {
+ .apb_clock_in = SPI2_CLK_IN,
+ .dma_transfer_enable = 0,
+ .rx_handshake_num = 12,
+ .clk_name = "spi2_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct platform_device fh_efuse_device = {
+ .name = "fh_efuse",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_efuse_resources),
+ .resource = fh_efuse_resources,
+ .dev = {
+ .platform_data = &fh_efuse_plat_data,
+ },
+};
+
+#ifdef CONFIG_FH_DMAC
+static struct fh_dma_platform_data fh_dma_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .nr_channels = 6,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_dma_device = {
+ .name = "fh_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_dma_resources),
+ .resource = fh_dma_resources,
+ .dev = {
+ .platform_data = &fh_dma_data,
+ },
+};
+#endif
+
+#ifdef CONFIG_FH_AXI_DMAC
+struct fh_axi_dma_platform_data axi_dma_plat_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_axi_dma_device = {
+ .name = "fh_axi_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_axi_dma_resources),
+ .resource = fh_axi_dma_resources,
+ .dev = {
+ .platform_data = &axi_dma_plat_data,
+ },
+};
+#endif
+
+
+
+static struct platform_device fh_spi0_device = {
+ .name = "fh_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi0_resources),
+ .resource = fh_spi0_resources,
+ .dev = {
+ .platform_data = &fh_spi0_data,
+ },
+};
+
+static struct platform_device fh_spi1_device = {
+ .name = "fh_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_spi1_resources),
+ .resource = fh_spi1_resources,
+ .dev = {
+ .platform_data = &fh_spi1_data,
+ },
+};
+
+static struct platform_device fh_spi2_device = {
+ .name = "fh_spi_slave",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi2_resources),
+ .resource = fh_spi2_resources,
+ .dev = {
+ .platform_data = &fh_spi2_data,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct platform_device fh_perf_device = {
+ .name = "fh_perf_mon",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_perf_resources),
+ .resource = fh_perf_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+static struct fh_wdt_platform_data fh_wdt_data = {
+ .mode = MODE_DISCRETE,
+};
+
+struct platform_device fh_wdt_device = {
+ .name = "fh_wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_wdt_resources),
+ .resource = fh_wdt_resources,
+ .dev = {
+ .platform_data = &fh_wdt_data,
+ }
+};
+
+static struct platform_device fh_pwm_device = {
+ .name = "fh_pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_pwm_resources),
+ .resource = fh_pwm_resources,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
+};
+
+static struct fh_usb_platform_data fh_usb_data = {
+ .dr_mode = "host",
+ .vbus_pwren = 47,
+};
+
+struct platform_device fh_usb_device = {
+ .name = "fh_usb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_usb_resources),
+ .resource = fh_usb_resources,
+ .dev = {
+ .platform_data = &fh_usb_data,
+ }
+};
+
+#ifdef CONFIG_FH_TSENSOR
+struct platform_device fh_tsensor_device = {
+ .name = "fh_tsensor",
+ .id = 0,
+};
+#endif
+
+static struct platform_device *fh8856v210_devices[] __initdata = {
+ &fh_uart0_device,
+ &fh_uart1_device,
+ &fh_uart2_device,
+ &fh_pinctrl_device,
+ &fh_i2c0_device,
+ &fh_i2c1_device,
+ &fh_i2c2_device,
+ &fh_rtc_device,
+ &fh_sd0_device,
+ &fh_sd1_device,
+ &fh_sadc_device,
+ &fh_gmac_device,
+ &fh_gpio0_device,
+ &fh_gpio1_device,
+ &fh_aes_device,
+ &fh_efuse_device,
+#ifdef CONFIG_FH_DMAC
+ &fh_dma_device,
+#endif
+#ifdef CONFIG_FH_AXI_DMAC
+ &fh_axi_dma_device,
+#endif
+ &fh_spi0_device,
+ &fh_spi1_device,
+ &fh_spi2_device,
+ &fh_i2s_device,
+ &fh_pwm_device,
+ &fh_wdt_device,
+ &fh_usb_device,
+#ifdef CONFIG_FH_PERF_MON
+ &fh_perf_device,
+#endif
+#ifdef CONFIG_FH_TSENSOR
+ &fh_tsensor_device,
+#endif
+};
+
+static struct mtd_partition fh_sf_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* Ramboot & U-Boot environment */
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* U-Boot */
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi_flash:256k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),4M(kernel),
+ * 8M(rootfs),
+ * -(app) */
+ /* two blocks with bad block table (and mirror) at the end */
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct mtd_partition fh_sf_nand_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_512K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi0.0:64k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),
+ * 4M(kernel),
+ * 8M(rootfs),
+ * -(app)
+ * two blocks with bad block table (and mirror) at the end
+ */
+};
+#endif
+
+static struct flash_platform_data fh_flash_platform_data = {
+ .name = "spi_flash",
+ .parts = fh_sf_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_parts),
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct flash_platform_data fh_nandflash_platform_data = {
+ .name = "spi_nandflash",
+ .parts = fh_sf_nand_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_nand_parts),
+};
+#endif
+
+static struct spi_board_info fh_spi_devices[] = {
+#ifdef CONFIG_MTD_SPI_NAND
+ {
+ .modalias = "spi-nand",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &fh_nandflash_platform_data,
+ },
+#endif
+ {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ /* multi wire should adapt spi para 'ctl_wire_support'*/
+ .mode = SPI_MODE_3 | SPI_RX_DUAL,
+ .max_speed_hz = 50000000,
+ .platform_data = &fh_flash_platform_data,
+ },
+
+};
+
+extern void early_print(const char *str, ...);
+
+static void __init fh_console_pre_init(struct fh_platform_uart *plat, int num)
+{
+ int idx = 0;
+
+ for (; idx < num; idx++) {
+ struct uart_port *port;
+
+ port = &fh_serial_ports[idx];
+ port->mapbase = plat[idx].mapbase;
+ port->fifosize = plat[idx].fifo_size;
+ port->uartclk = plat[idx].uartclk;
+
+ switch (idx) {
+ case 0:
+ port->membase = (unsigned char *)VA_UART0_REG_BASE;
+ break;
+ case 1:
+ port->membase = (unsigned char *)VA_UART1_REG_BASE;
+ break;
+ case 2:
+ port->membase = (unsigned char *)VA_UART2_REG_BASE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void __init fh8856v210_map_io(void)
+{
+ iotable_init(fh8856v210_io_desc, ARRAY_SIZE(fh8856v210_io_desc));
+ fh_console_pre_init(fh_uart_platform_data,
+ ARRAY_SIZE(fh_uart_platform_data));
+}
+
+
+static __init void fh8856v210_board_init(void)
+{
+ if (fh_is_8856v210())
+ fh_rtc_device.dev.platform_data = &rtc_plat_data[1];
+ platform_add_devices(fh8856v210_devices,
+ ARRAY_SIZE(fh8856v210_devices));
+ spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices));
+}
+void __init fh_timer_init_no_of(unsigned int iovbase,
+ unsigned int irqno);
+
+static void __init fh8856v210_init_early(void)
+{
+ fh_pmu_init();
+ fh_pinctrl_init(VA_PMU_REG_BASE + 0x80);
+}
+
+static void __init fh_time_init(void)
+{
+ unsigned int vtimerbase = (unsigned int)ioremap(TIMER_REG_BASE, SZ_4K);
+
+ fh_clk_init();
+ fh_timer_init_no_of(vtimerbase, TMR0_IRQ);
+
+}
+
+void __init fh_intc_init_no_of(unsigned int iovbase);
+static void __init fh_intc_init(void)
+{
+ unsigned int vintcbase = (unsigned int)ioremap(INTC_REG_BASE, SZ_4K);
+
+ fh_intc_init_no_of(vintcbase);
+
+}
+static void fh8856v210_restart
+ (enum reboot_mode mode, const char *cmd)
+{
+ fh_pmu_restart();
+}
+
+
+MACHINE_START(FH8856V210, "FH8856V210")
+ .atag_offset = 0x100,
+ .map_io = fh8856v210_map_io,
+ .init_irq = fh_intc_init,
+ .init_time = fh_time_init,
+ .init_machine = fh8856v210_board_init,
+ .init_early = fh8856v210_init_early,
+ .restart = fh8856v210_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-fh/fh8856v210/board_config.fh8856v210.appboard b/arch/arm/mach-fh/fh8856v210/board_config.fh8856v210.appboard
new file mode 100644
index 00000000..1c1a9153
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v210/board_config.fh8856v210.appboard
@@ -0,0 +1,45 @@
+#ifndef BOARD_CONFIG_H_
+#define BOARD_CONFIG_H_
+
+/*
+ * GPIO0 -> IRCUT_ON
+ * GPIO1 -> IRCUT_OFF
+ * GPIO2 -> USB_PWREN
+ * GPIO11 -> EMAC PHY Reset
+ * GPIO12 -> CIS_CLK
+ * GPIO13 -> CIS_RSTN
+ * GPIO14 -> CIS_PDN
+ * GPIO19 -> SD1_PWREN/WIFI_REG_ON
+ * GPIO20 -> AK7755 Reset
+ * GPIO24 -> LED0
+ * GPIO25 -> LED1
+ * GPIO26 -> Reset Configs
+ * GPIO27 -> AK7755 PowerDown
+ * GPIO28 -> IR
+ * GPIO53 -> USB_PWREN/SD0_PWREN
+ * GPIO55 -> SD1 WIFI Interrupt
+ */
+
+#define CONFIG_SD_CD_FIXED
+
+#define CONFIG_ISP_CLK_RATE 171000000
+#define CONFIG_JPEG_CLK_RATE 171000000
+#define CONFIG_VEU_CLK_RATE 240000000
+
+#define USB_VBUS_PWR_GPIO (47)
+
+#define ETH_GPIO "ETH", "GPIO48", "GPIO49", "GPIO50", "GPIO51", "GPIO52",\
+ "GPIO53", "GPIO54", "GPIO55", "GPIO56"
+
+#define CONFIG_PINCTRL_SELECT \
+ ETH_GPIO, "I2C0", "PWM2", "PWM3", "PWM4", "PWM5", "PWM6", \
+ "PWM7", "PWM8", "PWM9", "SADC_XAIN0", "SADC_XAIN1", \
+ "SD0_NO_WP", "SENSOR_CLK", "SSI0_4BIT", "UART0", \
+ "UART1", "GPIO4", "GPIO13", "GPIO30", "GPIO31", \
+ "GPIO32", "GPIO43", "GPIO44", "GPIO47", \
+\
+ "GPIO11", "GPIO14", "GPIO15", "GPIO16", "GPIO24", \
+ "GPIO25", "GPIO45", "GPIO46", "GPIO57", "GPIO58", "GPIO59", \
+ "GPIO60", "GPIO61", "GPIO62", "GPIO63"
+
+#endif /* BOARD_CONFIG_H_ */
diff --git a/arch/arm/mach-fh/fh8856v210/chip.c b/arch/arm/mach-fh/fh8856v210/chip.c
new file mode 100644
index 00000000..9bbb3c49
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v210/chip.c
@@ -0,0 +1,747 @@
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/clock.h>
+#include <mach/board_config.h>
+
+/*
+ * external oscillator
+ * fixed to 24M
+ */
+static struct fh_clk osc_clk = {
+ .name = "osc_clk",
+ .frequency = OSC_FREQUENCY,
+ .flag = CLOCK_FIXED,
+};
+
+/*
+ * phase-locked-loop device,
+ * generates a higher frequency clock
+ * from the external oscillator reference
+ *PLL_DDR
+ */
+
+static struct fh_clk pll_ddr_rclk = {
+ .name = "pll_ddr_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL0,
+ .en_reg_offset = REG_PMU_PLL0_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_CPU*/
+static struct fh_clk pll_cpu_pclk = {
+ .name = "pll_cpu_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+static struct fh_clk pll_cpu_rclk = {
+ .name = "pll_cpu_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_SYS*/
+static struct fh_clk pll_sys_pclk = {
+ .name = "pll_sys_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+
+static struct fh_clk pll_sys_rclk = {
+ .name = "pll_sys_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+static struct fh_clk pllsysp_div12_clk = {
+ .name = "pllsysp_div12_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk ddr_clk = {
+ .name = "ddr_clk",
+ .flag = CLOCK_NODIV,
+ .parent = {&pll_ddr_rclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8,
+};
+static struct fh_clk arm_clk = {
+ .name = "arm_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NOGATE|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1,
+};
+static struct fh_clk arc_clk = {
+ .name = "arc_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400000,
+};
+static struct fh_clk ahb_clk = {
+ .name = "ahb_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&osc_clk, &pll_sys_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf0000,
+};
+
+static struct fh_clk isp_aclk = {
+ .name = "isp_aclk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1,
+ .def_rate = CONFIG_ISP_CLK_RATE,
+};
+static struct fh_clk ispb_aclk = {
+ .name = "ispb_aclk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4,
+};
+
+static struct fh_clk vpu_clk = {
+ .name = "vpu_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80000000,
+};
+
+static struct fh_clk pix_clk = {
+ .name = "pix_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk jpeg_clk = {
+ .name = "jpeg_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x40000000,
+ .def_rate = CONFIG_JPEG_CLK_RATE,
+};
+
+static struct fh_clk bgm_clk = {
+ .name = "bgm_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x40000,
+};
+
+static struct fh_clk jpeg_adapt_clk = {
+ .name = "jpeg_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&jpeg_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2,
+};
+static struct fh_clk spi0_clk = {
+ .name = "spi0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100,
+};
+static struct fh_clk sdc0_clk = {
+ .name = "sdc0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x4,
+};
+static struct fh_clk spi2_clk = {
+ .name = "spi2_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100000,
+};
+static struct fh_clk spi1_clk = {
+ .name = "spi1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x200,
+};
+static struct fh_clk sdc1_clk = {
+ .name = "sdc1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x2,
+};
+
+static struct fh_clk veu_clk = {
+ .name = "veu_clk",
+ .flag = CLOCK_MULTI_PARENT,
+ .parent = {&pll_sys_pclk, &pll_sys_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x4,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0x7000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000000,
+ .def_rate = CONFIG_VEU_CLK_RATE,
+
+};
+
+static struct fh_clk veu_adapt_clk = {
+ .name = "veu_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&veu_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000000,
+
+};
+
+static struct fh_clk cis_clk_out = {
+ .name = "cis_clk_out",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800000,
+};
+
+static struct fh_clk eth_clk = {
+ .name = "eth_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x12000000,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x20000,
+};
+static struct fh_clk i2c0_clk = {
+ .name = "i2c0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400,
+};
+
+static struct fh_clk i2c1_clk = {
+ .name = "i2c1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800,
+};
+
+static struct fh_clk i2c2_clk = {
+ .name = "i2c2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x00003f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x00000008,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20000000,
+};
+
+static struct fh_clk pwm_clk = {
+ .name = "pwm_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x80,
+ .def_rate = 50000000,
+};
+
+static struct fh_clk uart0_clk = {
+ .name = "uart0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x4000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk uart1_clk = {
+ .name = "uart1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000,
+ .def_rate = 16666666,
+};
+static struct fh_clk uart2_clk = {
+ .name = "uart2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = 0,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x7f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk efuse_clk = {
+ .name = "efuse_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800000,
+};
+
+static struct fh_clk pts_clk = {
+ .name = "pts_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = CLOCK_NORESET,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0x1ff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL2,
+ .rst_reg_mask = 0x1,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk tmr0_clk = {
+ .name = "tmr0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x40000,
+};
+
+static struct fh_clk sadc_clk = {
+ .name = "sadc_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x7f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10000,
+};
+
+static struct fh_clk ac_clk = {
+ .name = "ac_clk",
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1000,
+};
+
+static struct fh_clk i2s_clk = {
+ .name = "i2s_clk",
+ .parent = {&ac_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000,
+};
+
+static struct fh_clk wdt_clk = {
+ .name = "wdt_clk",
+ .flag = 0,
+ .parent = {&ahb_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff00,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_APB_CTRL,
+ .rst_reg_mask = 0x100000,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk gpio0_db_clk = {
+ .name = "gpio0_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio1_db_clk = {
+ .name = "gpio1_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff0000,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x80000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20,
+};
+
+
+static struct fh_clk mipi_dphy_clk = {
+ .name = "mipi_dphy_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100000,
+};
+static struct fh_clk mipi_wrap_gate = {
+ .name = "mipi_wrap_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk rtc_hclk_gate = {
+ .name = "rtc_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk emac_hclk_gate = {
+ .name = "emac_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk usb_clk = {
+ .name = "usb_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk aes_hclk_gate = {
+ .name = "aes_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80,
+};
+static struct fh_clk ephy_clk_gate = {
+ .name = "ephy_clk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1,
+};
+static struct fh_clk sdc0_clk8x_gate = {
+ .name = "sdc0_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4,
+};
+static struct fh_clk sdc1_clk8x_gate = {
+ .name = "sdc1_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8,
+};
+static struct fh_clk mipic_pclk_gate = {
+ .name = "mipic_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio0_pclk_gate = {
+ .name = "gpio0_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x4000,
+};
+static struct fh_clk gpio1_pclk_gate = {
+ .name = "gpio1_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x40000000,
+};
+static struct fh_clk isp_hclk_gate = {
+ .name = "isp_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk veu_hclk_gate = {
+ .name = "veu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk bgm_hclk_gate = {
+ .name = "bgm_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x4000000,
+};
+static struct fh_clk adapt_hclk_gate = {
+ .name = "adapt_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x8000000,
+};
+static struct fh_clk jpg_hclk_gate = {
+ .name = "jpg_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk jpg_adapt_gate = {
+ .name = "jpg_adapt_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk vpu_hclk_gate = {
+ .name = "vpu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x40000000,
+};
+
+static struct fh_clk sdc0_clk_sample = {
+ .name = "sdc0_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf0000,
+};
+
+static struct fh_clk sdc0_clk_drv = {
+ .name = "sdc0_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00000,
+};
+
+static struct fh_clk sdc1_clk_sample = {
+ .name = "sdc1_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00,
+};
+
+static struct fh_clk sdc1_clk_drv = {
+ .name = "sdc1_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf000,
+};
+
+struct fh_clk *fh_clks[] = {
+ &osc_clk,
+ &pll_ddr_rclk,
+ &pll_cpu_pclk,
+ &pll_cpu_rclk,
+ &pll_sys_pclk,
+ &pll_sys_rclk,
+ &arm_clk,
+ &arc_clk,
+ &ahb_clk,
+ &ddr_clk,
+ &isp_aclk,
+ &ispb_aclk,
+ &jpeg_clk,
+ &jpeg_adapt_clk,
+ &vpu_clk,
+ &veu_clk,
+ &veu_adapt_clk,
+ &bgm_clk,
+ &mipi_dphy_clk,
+ &pllsysp_div12_clk,
+ &cis_clk_out,
+ &pix_clk,
+ &pts_clk,
+ &spi0_clk,
+ &spi1_clk,
+ &spi2_clk,
+ &sdc0_clk,
+ &sdc1_clk,
+ &uart0_clk,
+ &uart1_clk,
+ &uart2_clk,
+ &i2c0_clk,
+ &i2c1_clk,
+ &i2c2_clk,
+ &pwm_clk,
+ &wdt_clk,
+ &tmr0_clk,
+ &ac_clk,
+ &i2s_clk,
+ &sadc_clk,
+ &eth_clk,
+ &efuse_clk,
+ &gpio0_db_clk,
+ &gpio1_db_clk,
+ &mipi_wrap_gate,
+ &rtc_hclk_gate,
+ &emac_hclk_gate,
+ &usb_clk,
+ &aes_hclk_gate,
+ &ephy_clk_gate,
+ &sdc0_clk8x_gate,
+ &sdc1_clk8x_gate,
+ &gpio0_pclk_gate,
+ &gpio1_pclk_gate,
+ &mipic_pclk_gate,
+ &sdc0_clk_sample,
+ &sdc0_clk_drv,
+ &sdc1_clk_sample,
+ &sdc1_clk_drv,
+ &isp_hclk_gate,
+ &veu_hclk_gate,
+ &bgm_hclk_gate,
+ &adapt_hclk_gate,
+ &jpg_hclk_gate,
+ &jpg_adapt_gate,
+ &vpu_hclk_gate,
+ NULL,
+};
+EXPORT_SYMBOL(fh_clks);
diff --git a/arch/arm/mach-fh/fh8856v210/chip.h b/arch/arm/mach-fh/fh8856v210/chip.h
new file mode 100644
index 00000000..f2b2fcae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v210/chip.h
@@ -0,0 +1,420 @@
+#ifndef __ASM_ARCH_HL_H
+#define __ASM_ARCH_HL_H
+
+#include <linux/init.h>
+
+#define SRAM_GRANULARITY 32
+#define SRAM_SIZE (SZ_128K+SZ_8K)
+
+
+#define RAM_BASE (0x10000000)
+#define DDR_BASE (0xA0000000)
+
+
+#define PMU_REG_BASE (0xF0000000)
+#define TIMER_REG_BASE (0xF0C00000)
+#define GPIO0_REG_BASE (0xF0300000)
+#define GPIO1_REG_BASE (0xF4000000)
+#define UART0_REG_BASE (0xF0700000)
+#define UART1_REG_BASE (0xF0800000)
+#define SPI0_REG_BASE (0xF0500000)
+#define SPI1_REG_BASE (0xF0600000)
+#define SPI2_REG_BASE (0xF0640000)
+#define INTC_REG_BASE (0xE0200000)
+#define GMAC_REG_BASE (0xE0600000)
+#define USBC_REG_BASE (0xE0700000)
+#define DMAC_REG_BASE (0xE0300000)
+#define I2C1_REG_BASE (0xF0B00000)
+#define I2C0_REG_BASE (0xF0200000)
+#define I2C2_REG_BASE (0xF0100000)
+#define SDC0_REG_BASE (0xE2000000)
+#define SDC1_REG_BASE (0xE2200000)
+#define WDT_REG_BASE (0xF0D00000)
+#define PWM_REG_BASE (0xF0400000)
+#define I2S_REG_BASE (0xF0900000)
+#define ACW_REG_BASE (0xF0A00000)
+#define UART2_REG_BASE (0xF1300000)
+#define SADC_REG_BASE (0xF1200000)
+#define EFUSE_REG_BASE (0xF1600000)
+#define AES_REG_BASE (0xE8200000)
+#define RTC_REG_BASE (0xF1500000)
+#define DDRC_REG_BASE (0xED000000)
+#define CONSOLE_REG_BASE UART0_REG_BASE
+#define FH_UART_NUMBER 3
+
+#define FH_PMU_REG_SIZE 0x2110
+#define REG_PMU_CHIP_ID (0x0000)
+#define REG_PMU_IP_VER (0x0004)
+#define REG_PMU_FW_VER (0x0008)
+#define REG_PMU_CLK_SEL (0x000c)
+/*for HL REG_PMU_SYS_CTRL and CLK_SEL use one register */
+#define REG_PMU_SYS_CTRL (0x000c)
+#define REG_PMU_PLL0 (0x0010)
+#define REG_PMU_PLL1 (0x0014)
+#define REG_PMU_PLL0_CTRL (0x0018)
+#define REG_PMU_CLK_GATE (0x001c)
+#define REG_PMU_CLK_GATE1 (0x0020)
+#define REG_PMU_CLK_DIV0 (0x0024)
+#define REG_PMU_CLK_DIV1 (0x0028)
+#define REG_PMU_CLK_DIV2 (0x002c)
+#define REG_PMU_CLK_DIV3 (0x0030)
+#define REG_PMU_CLK_DIV4 (0x0034)
+#define REG_PMU_CLK_DIV5 (0x0038)
+#define REG_PMU_CLK_DIV6 (0x003c)
+#define REG_PMU_SWRST_MAIN_CTRL (0x0040)
+#define REG_PMU_SWRST_MAIN_CTRL2 (0x0044)
+#define REG_PMU_SWRST_AHB_CTRL (0x0048)
+#define REG_PMU_SWRST_APB_CTRL (0x004c)
+#define REG_PMU_SPC_IO_STATUS (0x0054)
+#define REG_PMU_SPC_FUN (0x0058)
+#define REG_PMU_CLK_DIV7 (0x005c)
+#define REG_PMU_CLK_DIV8 (0x0060)
+#define REG_PMU_PLL2 (0x0064)
+#define REG_PMU_PLL2_CTRL (0x0068)
+#define REG_PMU_PLL1_CTRL (0x006c)
+#define REG_PAD_PWR_SEL (0x0074)
+#define REG_PMU_SWRSTN_NSR (0x0078)
+#define REG_PMU_SWRSTN_NSR1 (0x007c)
+#define REG_PMU_ETHPHY_REG0 (0x2108)
+
+
+#define REG_PMU_PAD_BOOT_MODE_CFG (0x0080)
+#define REG_PMU_PAD_BOOT_SEL1_CFG (0x0084)
+#define REG_PMU_PAD_BOOT_SEL0_CFG (0x0088)
+#define REG_PMU_PAD_UART0_TX_CFG (0x008c)
+#define REG_PMU_PAD_UART0_RX_CFG (0x0090)
+#define REG_PMU_PAD_I2C0_SCL_CFG (0x0094)
+#define REG_PMU_PAD_I2C0_SDA_CFG (0x0098)
+#define REG_PMU_PAD_SENSOR_CLK_CFG (0x009c)
+#define REG_PMU_PAD_SENSOR_RSTN_CFG (0x00a0)
+#define REG_PMU_PAD_UART1_TX_CFG (0x00a4)
+#define REG_PMU_PAD_UART1_RX_CFG (0x00a8)
+#define REG_PMU_PAD_I2C1_SCL_CFG (0x00ac)
+#define REG_PMU_PAD_I2C1_SDA_CFG (0x00b0)
+#define REG_PMU_PAD_UART2_TX_CFG (0x00b4)
+#define REG_PMU_PAD_UART2_RX_CFG (0x00b8)
+#define REG_PMU_PAD_USB_PWREN_CFG (0x00bc)
+#define REG_PMU_PAD_PWM0_CFG (0x00c0)
+#define REG_PMU_PAD_PWM1_CFG (0x00c4)
+#define REG_PMU_PAD_PWM2_CFG (0x00c8)
+#define REG_PMU_PAD_PWM3_CFG (0x00cc)
+#define REG_PMU_PAD_MAC_RMII_CLK_CFG (0x00d0)
+#define REG_PMU_PAD_MAC_REF_CLK_CFG (0x00d4)
+#define REG_PMU_PAD_MAC_TXD0_CFG (0x00d8)
+#define REG_PMU_PAD_MAC_TXD1_CFG (0x00dc)
+#define REG_PMU_PAD_MAC_TXEN_CFG (0x00e0)
+#define REG_PMU_PAD_MAC_RXD0_CFG (0x00e4)
+#define REG_PMU_PAD_MAC_RXD1_CFG (0x00e8)
+#define REG_PMU_PAD_MAC_RXDV_CFG (0x00ec)
+#define REG_PMU_PAD_MAC_MDC_CFG (0x00f0)
+#define REG_PMU_PAD_MAC_MDIO_CFG (0x00f4)
+#define REG_PMU_PAD_SD1_CLK_CFG (0x00f8)
+#define REG_PMU_PAD_SD1_CD_CFG (0x00fc)
+#define REG_PMU_PAD_SD1_CMD_RSP_CFG (0x0100)
+#define REG_PMU_PAD_SD1_DATA_0_CFG (0x0104)
+#define REG_PMU_PAD_SD1_DATA_1_CFG (0x0108)
+#define REG_PMU_PAD_SD1_DATA_2_CFG (0x010c)
+#define REG_PMU_PAD_SD1_DATA_3_CFG (0x0110)
+#define REG_PMU_PAD_GPIO_0_CFG (0x0114)
+#define REG_PMU_PAD_GPIO_1_CFG (0x0118)
+#define REG_PMU_PAD_GPIO_2_CFG (0x011c)
+#define REG_PMU_PAD_GPIO_3_CFG (0x0120)
+#define REG_PMU_PAD_GPIO_4_CFG (0x0124)
+#define REG_PMU_PAD_SSI0_CLK_CFG (0x0128)
+#define REG_PMU_PAD_SSI0_CSN_0_CFG (0x012c)
+#define REG_PMU_PAD_SSI0_TXD_CFG (0x0130)
+#define REG_PMU_PAD_SSI0_RXD_CFG (0x0134)
+#define REG_PMU_PAD_SSI0_D2_CFG (0x0138)
+#define REG_PMU_PAD_SSI0_D3_CFG (0x013c)
+#define REG_PMU_PAD_SSI1_CLK_CFG (0x0140)
+#define REG_PMU_PAD_SSI1_CSN_0_CFG (0x0144)
+#define REG_PMU_PAD_SSI1_TXD_CFG (0x0148)
+#define REG_PMU_PAD_SSI1_RXD_CFG (0x014c)
+#define REG_PMU_PAD_SD0_CD_CFG (0x0150)
+#define REG_PMU_PAD_SD0_CLK_CFG (0x0154)
+#define REG_PMU_PAD_SD0_CMD_RSP_CFG (0x0158)
+#define REG_PMU_PAD_SD0_DATA_0_CFG (0x015c)
+#define REG_PMU_PAD_SD0_DATA_1_CFG (0x0160)
+#define REG_PMU_PAD_SD0_DATA_2_CFG (0x0164)
+#define REG_PMU_PAD_SD0_DATA_3_CFG (0x0168)
+#define REG_PMU_PAD_SADC_XAIN0_CFG (0x016c)
+#define REG_PMU_PAD_SADC_XAIN1_CFG (0x0170)
+#define REG_PMU_PAD_SADC_XAIN2_CFG (0x0174)
+#define REG_PMU_PAD_SADC_XAIN3_CFG (0x0178)
+#define REG_PMU_PAD_GPIO_28_CFG (0x017c)
+#define REG_PMU_PAD_GPIO_29_CFG (0x0180)
+
+#define REG_PMU_ARM_INT_0 (0x01e0)
+#define REG_PMU_ARM_INT_1 (0x01e4)
+#define REG_PMU_ARM_INT_2 (0x01e8)
+#define REG_PMU_A625_INT_0 (0x01ec)
+#define REG_PMU_A625_INT_1 (0x01f0)
+#define REG_PMU_A625_INT_2 (0x01f4)
+#define REG_PMU_DMA (0x01f8)
+#define REG_PMU_WDT_CTRL (0x01fc)
+#define REG_PMU_DBG_STAT0 (0x0200)
+#define REG_PMU_DBG_STAT1 (0x0204)
+#define REG_PMU_DBG_STAT2 (0x0208)
+#define REG_PMU_DBG_STAT3 (0x020c)
+#define REG_PMU_USB_SYS (0x0210)
+#define REG_PMU_USB_CFG (0x0214)
+#define REG_PMU_USB_TUNE (0x0218)
+#define REG_PMU_USB_SYS1 (0x0228)
+#define REG_PMU_PTSLO (0x022c)
+#define REG_PMU_PTSHI (0x0230)
+#define REG_PMU_USER0 (0x0234)
+#define REG_PMU_BOOT_MODE (0x0330)
+#define REG_PMU_DDR_SIZE (0x0334)
+#define REG_PMU_CHIP_INFO (0x033C)
+#define REG_PMU_EPHY_PARAM (0x0340)
+#define REG_PMU_RTC_PARAM (0x0344)
+#define REG_PMU_SD1_FUNC_SEL (0x03a0)
+#define REG_PMU_PRDCID_CTRL0 (0x0500)
+#define REG_PMU_A625BOOT0 (0x2000)
+#define REG_PMU_A625BOOT1 (0x2004)
+#define REG_PMU_A625BOOT2 (0x2008)
+#define REG_PMU_A625BOOT3 (0x200c)
+#define REG_PMU_A625_START_CTRL (0x2010)
+#define REG_PMU_ARC_INTC_MASK (0x2014)
+
+#define FH_GMAC_AHB_RESET (1<<17)
+#define FH_GMAC_SPEED_100M (1<<24)
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+#define PMU_RXDV_GPIO_SWITCH (REG_PMU_PAD_MAC_RXDV_CFG)
+#define PMU_RXDV_GPIO_MASK (0x0f000000)
+#define PMU_RXDV_GPIO_VAL (0x01000000)
+
+#define PMU_DWI2S_CLK_SEL_REG (REG_PMU_CLK_SEL)
+#define PMU_DWI2S_CLK_SEL_SHIFT (1)
+#define PMU_DWI2S_CLK_DIV_REG (REG_PMU_CLK_DIV6)
+#define PMU_DWI2S_CLK_DIV_SHIFT (0)
+
+/*ATTENTION: written by ARC */
+#define PMU_ARM_INT_MASK (0x01ec)
+#define PMU_ARM_INT_RAWSTAT (0x01f0)
+#define PMU_ARM_INT_STAT (0x01f4)
+
+#define PMU_A625_INT_MASK (0x01e0)
+#define PMU_A625_INT_RAWSTAT (0x01e4)
+#define PMU_A625_INT_STAT (0x01e8)
+
+#define PMU_IRQ 0
+#define DDRC_IRQ 1
+#define WDT_IRQ 2
+#define TMR0_IRQ 3
+#define VEU_IRQ 4
+#define PERF_IRQ 5
+#define VPU_IRQ 9
+#define I2C0_IRQ 11
+#define I2C1_IRQ 12
+#define JPEG_IRQ 13
+#define BGM_IRQ 14
+#define VEU_LOOP_IRQ 15
+#define AES_IRQ 16
+#define MIPIC_IRQ 17
+#define MIPI_WRAP_IRQ 18
+#define ACW_IRQ 19
+#define SADC_IRQ 20
+#define SPI1_IRQ 21
+#define JPEG_LOOP_IRQ 22
+#define DMAC0_IRQ 23
+#define DMAC1_IRQ 24
+#define I2S0_IRQ 25
+#define GPIO0_IRQ 26
+#define SPI0_IRQ 28
+#define ARC_SW_IRQ 29
+#define UART0_IRQ 30
+#define UART1_IRQ 31
+#define ARM_SW_IRQ 32
+#define RTC_IRQ 33
+#define PWM_IRQ 36
+#define SPI2_IRQ 38
+#define USBC_IRQ 39
+#define GPIO1_IRQ 40
+#define UART2_IRQ 41
+#define SDC0_IRQ 42
+#define SDC1_IRQ 43
+#define GMAC_IRQ 44
+#define EPHY_IRQ 45
+#define I2C2_IRQ 46
+#define RTC_ALM_IRQ 47
+#define RTC_CORE_IRQ 48
+/* because chips with some same function in different */
+/* pmu register, use wrap marco to make code to be same */
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+
+#define MEM_START_PHY_ADDR DDR_BASE
+#define MEM_SIZE 0x4000000
+
+
+#define NR_INTERNAL_IRQS (64)
+#define NR_EXTERNAL_IRQS (64)
+/*#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS)*/
+
+/* SWRST_MAIN_CTRL */
+#define CPU_RSTN_BIT (0)
+#define UTMI_RSTN_BIT (1)
+#define DDRPHY_RSTN_BIT (2)
+#define DDRC_RSTN_BIT (3)
+#define GPIO0_DB_RSTN_BIT (4)
+#define GPIO1_DB_RSTN_BIT (5)
+#define PIXEL_RSTN_BIT (6)
+#define PWM_RSTN_BIT (7)
+#define SPI0_RSTN_BIT (8)
+#define SPI1_RSTN_BIT (9)
+#define I2C0_RSTN_BIT (10)
+#define I2C1_RSTN_BIT (11)
+#define ACODEC_RSTN_BIT (12)
+#define I2S_RSTN_BIT (13)
+#define UART0_RSTN_BIT (14)
+#define UART1_RSTN_BIT (15)
+#define SADC_RSTN_BIT (16)
+#define ADAPT_RSTN_BIT (17)
+#define TMR_RSTN_BIT (18)
+#define UART2_RSTN_BIT (19)
+#define SPI2_RSTN_BIT (20)
+#define JPG_ADAPT_RSTN_BIT (21)
+#define ARC_RSTN_BIT (22)
+#define EFUSE_RSTN_BIT (23)
+#define JPG_RSTN_BIT (24)
+#define VEU_RSTN_BIT (25)
+#define VPU_RSTN_BIT (26)
+#define ISP_RSTN_BIT (27)
+#define BGM_RSTN_BIT (28)
+#define I2C2_RSTN_BIT (29)
+#define EPHY_RSTN_BIT (30)
+#define SYS_RSTN_BIT (31)
+
+/* SWRST_AHB_CTRL */
+#define EMC_HRSTN_BIT (0)
+#define SDC1_HRSTN_BIT (1)
+#define SDC0_HRSTN_BIT (2)
+#define AES_HRSTN_BIT (3)
+#define DMAC0_HRSTN_BIT (4)
+#define INTC_HRSTN_BIT (5)
+#define JPEG_ADAPT_HRSTN_BIT (7)
+#define JPEG_HRSTN_BIT (8)
+#define VCU_HRSTN_BIT (9)
+#define VPU_HRSTN_BIT (10)
+#define ISP_HRSTN_BIT (11)
+#define USB_HRSTN_BIT (12)
+#define HRSTN_BIT (13)
+#define EMAC_HRSTN_BIT (17)
+#define DDRC_HRSTN_BIT (19)
+#define DMAC1_HRSTN_BIT (20)
+#define BGM_HRSTN_BIT (22)
+#define ADAPT_HRSTN_BIT (23)
+
+/* SWRST_APB_CTRL */
+#define ACODEC_PRSTN_BIT (0)
+#define I2S_PRSTN_BIT (1)
+#define UART1_PRSTN_BIT (2)
+#define UART0_PRSTN_BIT (3)
+#define SPI0_PRSTN_BIT (4)
+#define SPI1_PRSTN_BIT (5)
+#define GPIO0_PRSTN_BIT (6)
+#define UART2_PRSTN_BIT (7)
+#define I2C2_PRSTN_BIT (8)
+#define I2C0_PRSTN_BIT (9)
+#define I2C1_PRSTN_BIT (10)
+#define TMR_PRSTN_BIT (11)
+#define PWM_PRSTN_BIT (12)
+#define MIPIW_PRSTN_BIT (13)
+#define MIPIC_PRSTN_BIT (14)
+#define RTC_PRSTN_BIT (15)
+#define SADC_PRSTN_BIT (16)
+#define EFUSE_PRSTN_BIT (17)
+#define SPI2_PRSTN_BIT (18)
+#define WDT_PRSTN_BIT (19)
+#define GPIO1_PRSTN_BIT (20)
+
+/* timer clk fpga 1M,soc 50M*/
+#ifdef CONFIG_FPGA
+#define TIMER_CLK (1000000)
+#else
+#define TIMER_CLK (50000000)
+#endif
+
+#define UART1_TX_HW_HANDSHAKE (9)
+#define UART1_RX_HW_HANDSHAKE (8)
+#define UART2_TX_HW_HANDSHAKE (13)
+#define UART2_RX_HW_HANDSHAKE (12)
+#define UART1_DMA_TX_CHAN (4)
+#define UART1_DMA_RX_CHAN (5)
+#define UART2_DMA_TX_CHAN (4)
+#define UART2_DMA_RX_CHAN (5)
+
+/*sdio*/
+#define SIMPLE_0 (0)
+#define SIMPLE_22 (1)
+#define SIMPLE_45 (2)
+#define SIMPLE_67 (3)
+#define SIMPLE_90 (4)
+#define SIMPLE_112 (5)
+#define SIMPLE_135 (6)
+#define SIMPLE_157 (7)
+#define SIMPLE_180 (8)
+#define SIMPLE_202 (9)
+#define SIMPLE_225 (10)
+#define SIMPLE_247 (11)
+#define SIMPLE_270 (12)
+#define SIMPLE_292 (13)
+#define SIMPLE_315 (14)
+#define SIMPLE_337 (15)
+
+
+
+#define SDIO0_RST_BIT (~UL(1<<2))
+#define SDIO0_CLK_RATE (50000000)
+#define SDIO0_CLK_DRV_SHIFT (20)
+#define SDIO0_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO0_CLK_SAM_SHIFT (16)
+#define SDIO0_CLK_SAM_DEGREE (SIMPLE_0)
+
+
+#define SDIO1_RST_BIT (~UL(1<<1))
+#define SDIO1_CLK_RATE (50000000)
+#define SDIO1_CLK_DRV_SHIFT (12)
+#define SDIO1_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO1_CLK_SAM_SHIFT (8)
+#define SDIO1_CLK_SAM_DEGREE (SIMPLE_0)
+
+#define SDC0_HRSTN (0x1<<2)
+#define SDC1_HRSTN (0x1<<1)
+#define SDC2_HRSTN (0)
+
+
+/*usb*/
+#define IRQ_UHOST USBC_IRQ
+#define FH_PA_OTG USBC_REG_BASE
+#define IRQ_OTG IRQ_UHOST
+#define FH_SZ_USBHOST SZ_1M
+#define FH_SZ_OTG SZ_1M
+
+#define USB_UTMI_RST_BIT (0x1<<1)
+#define USB_PHY_RST_BIT (0x11)
+#define USB_SLEEP_MODE_BIT (0x1<<24)
+#define USB_IDDQ_PWR_BIT (0x1<<10)
+
+
+/* Specific Uart Number */
+#define FH_UART_NUMBER 3
+#define CLK_SCAN_BIT_POS (28)
+#define INSIDE_PHY_ENABLE_BIT_POS (24)
+#define MAC_REF_CLK_DIV_MASK (0x0f)
+#define MAC_REF_CLK_DIV_BIT_POS (24)
+#define MAC_PAD_RMII_CLK_MASK (0x0f)
+#define MAC_PAD_RMII_CLK_BIT_POS (24)
+#define MAC_PAD_MAC_REF_CLK_BIT_POS (28)
+#define ETH_REF_CLK_OUT_GATE_BIT_POS (25)
+#define ETH_RMII_CLK_OUT_GATE_BIT_POS (28)
+#define IN_OR_OUT_PHY_SEL_BIT_POS (26)
+#define INSIDE_CLK_GATE_BIT_POS (0)
+#define INSIDE_PHY_SHUTDOWN_BIT_POS (31)
+#define INSIDE_PHY_RST_BIT_POS (30)
+#define INSIDE_PHY_TRAINING_BIT_POS (27)
+#define INSIDE_PHY_TRAINING_MASK (0x0f)
+
+#define TRAINING_EFUSE_ACTIVE_BIT_POS 4
+
+#endif /* __ASM_ARCH_HL_H */
diff --git a/arch/arm/mach-fh/fh8856v210/iopad.h b/arch/arm/mach-fh/fh8856v210/iopad.h
new file mode 100644
index 00000000..ebc24024
--- /dev/null
+++ b/arch/arm/mach-fh/fh8856v210/iopad.h
@@ -0,0 +1,729 @@
+#include <mach/pinctrl.h>
+#include <mach/pinctrl_osdep.h>
+#include <mach/board_config.h>
+
+/* PINCTRL_FUNC */
+PINCTRL_FUNC(GPIO30, 0, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO31, 1, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 1, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO32, 2, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 2, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 2, FUNC2, PUPD_UP, 0);
+PINCTRL_FUNC(UART0_TX, 3, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO33, 3, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART0_RX, 4, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO34, 4, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C0_SCL, 5, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO35, 5, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(I2C0_SDA, 6, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO36, 6, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(SENSOR_CLK, 7, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO12, 7, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO13, 8, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 9, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO39, 9, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 9, FUNC3, PUPD_NONE, 3);
+PINCTRL_FUNC(TEST_O_INT_RMII_CLK, 9, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 10, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO40, 10, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 10, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_0, 10, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 11, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO37, 11, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 11, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 11, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 11, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_1, 11, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 12, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO38, 12, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 12, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 12, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 12, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXEN, 12, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 13, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO41, 13, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM4, 13, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 13, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 13, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_0, 13, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 14, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO42, 14, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM5, 14, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 14, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 14, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_1, 14, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 15, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO47, 15, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 15, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_CRSDV, 15, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM0, 16, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO43, 16, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SCL, 16, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 16, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_0, 16, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM1, 17, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO44, 17, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SDA, 17, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 17, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_1, 17, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 18, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO45, 18, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 19, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO46, 19, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RMII_CLK, 20, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO48, 20, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 20, FUNC2, PUPD_NONE, 3);
+PINCTRL_FUNC(PWM2, 20, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_REF_CLK, 21, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(MAC_TXD_0, 22, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO49, 22, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 22, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM3, 22, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXD_1, 23, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO50, 23, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 23, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM4, 23, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXEN, 24, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO51, 24, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 24, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM5, 24, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_0, 25, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO52, 25, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 25, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM6, 25, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_1, 26, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO53, 26, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 26, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM7, 26, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXDV, 27, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO54, 27, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 27, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM8, 27, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 28, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO55, 28, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 28, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 29, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO56, 29, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 30, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO57, 30, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 30, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 31, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO58, 31, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 31, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO59, 32, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 32, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 33, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO60, 33, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 33, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 34, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO61, 34, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 34, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 35, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO62, 35, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 35, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 36, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO63, 36, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TRSTN, 37, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO0, 37, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DO, 37, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DO, 37, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CLK, 37, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CLK, 37, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADDAT, 37, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM6, 37, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDC, 37, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDO, 38, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO1, 38, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DI, 38, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DI, 38, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CSN_0, 38, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DADAT, 38, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM7, 38, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_I, 38, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDI, 39, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO2, 39, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_CLK, 39, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_CLK, 39, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_TXD, 39, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_TXD, 39, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADBCLK, 39, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM8, 39, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_O, 39, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TCK, 40, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO3, 40, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_WS, 40, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_WS, 40, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_RXD, 40, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_RXD, 40, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADLRC, 40, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 40, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDIO_I, 40, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TMS, 41, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO4, 41, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_MCLK, 41, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 41, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 41, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDC, 41, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI0_CLK, 42, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO5, 42, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CLK, 42, FUNC4, PUPD_NONE, 3);
+PINCTRL_FUNC(SSI0_CSN_0, 43, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO6, 43, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CMD_RSP, 43, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_TXD, 44, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO7, 44, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_0, 44, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_RXD, 45, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO8, 45, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_1, 45, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D2, 46, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO9, 46, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_TX, 46, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SCL, 46, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_2, 46, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D3, 47, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO10, 47, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_RX, 47, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SDA, 47, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_3, 47, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 48, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO11, 48, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CLK, 48, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 49, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CSN_0, 49, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 50, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO15, 50, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_TXD, 50, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 51, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO16, 51, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_RXD, 51, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CD, 52, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO17, 52, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARC_JTAG_TRSTN, 52, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(PAE_JTAG_TRSTN, 52, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD0_CLK, 53, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO18, 53, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 53, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDO, 53, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDO, 53, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CMD_RSP, 54, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO19, 54, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 54, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDI, 54, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDI, 54, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_0, 55, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO20, 55, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 55, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TCK, 55, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TCK, 55, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_1, 56, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO21, 56, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 56, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TMS, 56, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TMS, 56, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_2, 57, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO22, 57, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_TX, 57, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SCL, 57, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DABCLK, 57, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_3, 58, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO23, 58, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 58, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_RX, 58, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SDA, 58, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DALRC, 58, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SADC_XAIN0, 59, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO26, 59, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN1, 60, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO27, 60, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN2, 61, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO24, 61, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN3, 62, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO25, 62, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO28, 63, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 63, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM10, 63, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_DBG_CLK, 63, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 63, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXEN, 63, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 63, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO29, 64, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 64, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM11, 64, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(RTC_CLK, 64, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 64, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_OE, 64, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 64, FUNC7, PUPD_NONE, 0);
+
+
+/* PINCTRL_MUX */
+
+PINCTRL_MUX(AC_I2S_CLK, 0, &PAD39_AC_I2S_CLK);
+PINCTRL_MUX(AC_I2S_DI, 0, &PAD38_AC_I2S_DI);
+PINCTRL_MUX(AC_I2S_DO, 0, &PAD37_AC_I2S_DO);
+PINCTRL_MUX(AC_I2S_WS, 0, &PAD40_AC_I2S_WS);
+PINCTRL_MUX(AC_MCLK, 0, &PAD41_AC_MCLK);
+
+PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD55_ARC_JTAG_TCK);
+PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD54_ARC_JTAG_TDI);
+PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD53_ARC_JTAG_TDO);
+PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD56_ARC_JTAG_TMS);
+PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD52_ARC_JTAG_TRSTN);
+
+PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD40_ARM_JTAG_TCK);
+PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD39_ARM_JTAG_TDI);
+PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD38_ARM_JTAG_TDO);
+PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD41_ARM_JTAG_TMS);
+PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD37_ARM_JTAG_TRSTN);
+
+PINCTRL_MUX(DW_I2S_CLK, 0, &PAD39_DW_I2S_CLK);
+PINCTRL_MUX(DW_I2S_DI, 0, &PAD38_DW_I2S_DI);
+PINCTRL_MUX(DW_I2S_DO, 0, &PAD37_DW_I2S_DO);
+PINCTRL_MUX(DW_I2S_WS, 0, &PAD40_DW_I2S_WS);
+
+PINCTRL_MUX(ETH_LINK_ACT, 1, &PAD1_ETH_LINK_ACT,
+ &PAD63_ETH_LINK_ACT);
+PINCTRL_MUX(ETH_LINK_SPD, 1, &PAD2_ETH_LINK_SPD,
+ &PAD64_ETH_LINK_SPD);
+PINCTRL_MUX(ETH_LINK_STA, 1, &PAD2_ETH_LINK_STA,
+ &PAD64_ETH_LINK_STA);
+
+PINCTRL_MUX(I2C0_SCL, 0, &PAD5_I2C0_SCL);
+PINCTRL_MUX(I2C0_SDA, 0, &PAD6_I2C0_SDA);
+
+PINCTRL_MUX(I2C1_SCL, 2, &PAD11_I2C1_SCL, &PAD30_I2C1_SCL, &PAD46_I2C1_SCL);
+PINCTRL_MUX(I2C1_SDA, 2, &PAD12_I2C1_SDA, &PAD31_I2C1_SDA, &PAD47_I2C1_SDA);
+
+PINCTRL_MUX(I2C2_SCL, 1, &PAD16_I2C2_SCL, &PAD57_I2C2_SCL);
+PINCTRL_MUX(I2C2_SDA, 1, &PAD17_I2C2_SDA, &PAD58_I2C2_SDA);
+
+PINCTRL_MUX(MAC_MDC, 0, &PAD28_MAC_MDC, &PAD63_MAC_MDC);
+PINCTRL_MUX(MAC_MDIO, 0, &PAD29_MAC_MDIO, &PAD64_MAC_MDIO);
+PINCTRL_MUX(MAC_REF_CLK, 0, &PAD21_MAC_REF_CLK);
+PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD20_MAC_RMII_CLK);
+PINCTRL_MUX(MAC_RXDV, 0, &PAD27_MAC_RXDV);
+PINCTRL_MUX(MAC_RXD_0, 0, &PAD25_MAC_RXD_0);
+PINCTRL_MUX(MAC_RXD_1, 0, &PAD26_MAC_RXD_1);
+PINCTRL_MUX(MAC_TXD_0, 0, &PAD22_MAC_TXD_0);
+PINCTRL_MUX(MAC_TXD_1, 0, &PAD23_MAC_TXD_1);
+PINCTRL_MUX(MAC_TXEN, 0, &PAD24_MAC_TXEN);
+
+PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD55_PAE_JTAG_TCK);
+PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD54_PAE_JTAG_TDI);
+PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD53_PAE_JTAG_TDO);
+PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD56_PAE_JTAG_TMS);
+PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD52_PAE_JTAG_TRSTN);
+
+PINCTRL_MUX(PWM0, 0, &PAD16_PWM0);
+PINCTRL_MUX(PWM1, 0, &PAD17_PWM1);
+PINCTRL_MUX(PWM10, 0, &PAD63_PWM10);
+PINCTRL_MUX(PWM11, 0, &PAD64_PWM11);
+PINCTRL_MUX(PWM2, 0, &PAD11_PWM2, &PAD18_PWM2, &PAD20_PWM2);
+PINCTRL_MUX(PWM3, 0, &PAD12_PWM3, &PAD19_PWM3, &PAD22_PWM3);
+PINCTRL_MUX(PWM4, 0, &PAD13_PWM4, &PAD23_PWM4);
+PINCTRL_MUX(PWM5, 0, &PAD14_PWM5, &PAD24_PWM5);
+PINCTRL_MUX(PWM6, 1, &PAD25_PWM6, &PAD37_PWM6);
+PINCTRL_MUX(PWM7, 1, &PAD26_PWM7, &PAD38_PWM7);
+PINCTRL_MUX(PWM8, 1, &PAD27_PWM8, &PAD39_PWM8);
+PINCTRL_MUX(PWM9, 1, &PAD28_PWM9, &PAD40_PWM9);
+
+PINCTRL_MUX(RTC_CLK, 0, &PAD64_RTC_CLK);
+
+PINCTRL_MUX(SADC_XAIN0, 0, &PAD59_SADC_XAIN0);
+PINCTRL_MUX(SADC_XAIN1, 0, &PAD60_SADC_XAIN1);
+PINCTRL_MUX(SADC_XAIN2, 0, &PAD61_SADC_XAIN2);
+PINCTRL_MUX(SADC_XAIN3, 0, &PAD62_SADC_XAIN3);
+
+PINCTRL_MUX(SD0_CD, 0, &PAD52_SD0_CD);
+PINCTRL_MUX(SD0_CLK, 0, &PAD53_SD0_CLK);
+PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD54_SD0_CMD_RSP);
+PINCTRL_MUX(SD0_DATA_0, 0, &PAD55_SD0_DATA_0);
+PINCTRL_MUX(SD0_DATA_1, 0, &PAD56_SD0_DATA_1);
+PINCTRL_MUX(SD0_DATA_2, 0, &PAD57_SD0_DATA_2);
+PINCTRL_MUX(SD0_DATA_3, 0, &PAD58_SD0_DATA_3);
+
+PINCTRL_MUX(SD1_CD, 0, &PAD10_SD1_CD, &PAD22_SD1_CD, &PAD31_SD1_CD,
+ &PAD41_SD1_CD, &PAD63_SD1_CD);
+PINCTRL_MUX(SD1_CLK, 0, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP, 0, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0, 0, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1, 0, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2, 0, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3, 0, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+PINCTRL_MUX(SENSOR_CLK, 0, &PAD7_SENSOR_CLK);
+
+PINCTRL_MUX(SSI0_CLK, 0, &PAD42_SSI0_CLK);
+PINCTRL_MUX(SSI0_D2, 0, &PAD46_SSI0_D2);
+PINCTRL_MUX(SSI0_D3, 0, &PAD47_SSI0_D3);
+PINCTRL_MUX(SSI0_RXD, 0, &PAD45_SSI0_RXD);
+PINCTRL_MUX(SSI0_TXD, 0, &PAD44_SSI0_TXD);
+
+PINCTRL_MUX(SSI1_CLK, 2, &PAD11_SSI1_CLK, &PAD37_SSI1_CLK, &PAD48_SSI1_CLK,
+ &PAD53_SSI1_CLK);
+PINCTRL_MUX(SSI1_RXD, 2, &PAD14_SSI1_RXD, &PAD40_SSI1_RXD, &PAD51_SSI1_RXD,
+ &PAD55_SSI1_RXD);
+PINCTRL_MUX(SSI1_TXD, 2, &PAD13_SSI1_TXD, &PAD39_SSI1_TXD, &PAD50_SSI1_TXD,
+ &PAD54_SSI1_TXD);
+
+PINCTRL_MUX(SSI2_CLK, 1, &PAD37_SSI2_CLK, &PAD48_SSI2_CLK);
+PINCTRL_MUX(SSI2_CSN_0, 1, &PAD38_SSI2_CSN_0, &PAD49_SSI2_CSN_0);
+PINCTRL_MUX(SSI2_RXD, 1, &PAD40_SSI2_RXD, &PAD51_SSI2_RXD);
+PINCTRL_MUX(SSI2_TXD, 1, &PAD39_SSI2_TXD, &PAD50_SSI2_TXD);
+
+PINCTRL_MUX(UART0_RX, 0, &PAD4_UART0_RX);
+PINCTRL_MUX(UART0_TX, 0, &PAD3_UART0_TX);
+
+PINCTRL_MUX(UART1_RX, 0, &PAD10_UART1_RX, &PAD33_UART1_RX, &PAD47_UART1_RX);
+PINCTRL_MUX(UART1_TX, 0, &PAD9_UART1_TX, &PAD32_UART1_TX, &PAD46_UART1_TX);
+
+PINCTRL_MUX(UART2_RX, 0, &PAD14_UART2_RX, &PAD17_UART2_RX, &PAD35_UART2_RX,
+ &PAD58_UART2_RX);
+PINCTRL_MUX(UART2_TX, 0, &PAD13_UART2_TX, &PAD16_UART2_TX, &PAD34_UART2_TX,
+ &PAD57_UART2_TX);
+
+PINCTRL_MUX(USB_PWREN, 0, &PAD15_USB_PWREN, &PAD41_USB_PWREN);
+
+PINCTRL_MUX(GPIO0, 0, &PAD37_GPIO0);
+PINCTRL_MUX(GPIO1, 0, &PAD38_GPIO1);
+PINCTRL_MUX(GPIO2, 0, &PAD39_GPIO2);
+PINCTRL_MUX(GPIO3, 0, &PAD40_GPIO3);
+PINCTRL_MUX(GPIO4, 0, &PAD41_GPIO4);
+PINCTRL_MUX(GPIO5, 0, &PAD42_GPIO5);
+PINCTRL_MUX(GPIO6, 0, &PAD43_GPIO6);
+PINCTRL_MUX(GPIO7, 0, &PAD44_GPIO7);
+PINCTRL_MUX(GPIO8, 0, &PAD45_GPIO8);
+PINCTRL_MUX(GPIO9, 0, &PAD46_GPIO9);
+PINCTRL_MUX(GPIO10, 0, &PAD47_GPIO10);
+PINCTRL_MUX(GPIO11, 0, &PAD48_GPIO11);
+PINCTRL_MUX(GPIO12, 0, &PAD7_GPIO12);
+PINCTRL_MUX(GPIO13, 0, &PAD8_GPIO13);
+PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14);
+PINCTRL_MUX(GPIO15, 0, &PAD50_GPIO15);
+PINCTRL_MUX(GPIO16, 0, &PAD51_GPIO16);
+PINCTRL_MUX(GPIO17, 0, &PAD52_GPIO17);
+PINCTRL_MUX(GPIO18, 0, &PAD53_GPIO18);
+PINCTRL_MUX(GPIO19, 0, &PAD54_GPIO19);
+PINCTRL_MUX(GPIO20, 0, &PAD55_GPIO20);
+PINCTRL_MUX(GPIO21, 0, &PAD56_GPIO21);
+PINCTRL_MUX(GPIO22, 0, &PAD57_GPIO22);
+PINCTRL_MUX(GPIO23, 0, &PAD58_GPIO23);
+PINCTRL_MUX(GPIO24, 0, &PAD61_GPIO24);
+PINCTRL_MUX(GPIO25, 0, &PAD62_GPIO25);
+PINCTRL_MUX(GPIO26, 0, &PAD59_GPIO26);
+PINCTRL_MUX(GPIO27, 0, &PAD60_GPIO27);
+PINCTRL_MUX(GPIO28, 0, &PAD63_GPIO28);
+PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29);
+PINCTRL_MUX(GPIO30, 0, &PAD0_GPIO30);
+PINCTRL_MUX(GPIO31, 0, &PAD1_GPIO31);
+PINCTRL_MUX(GPIO32, 0, &PAD2_GPIO32);
+PINCTRL_MUX(GPIO33, 0, &PAD3_GPIO33);
+PINCTRL_MUX(GPIO34, 0, &PAD4_GPIO34);
+PINCTRL_MUX(GPIO35, 0, &PAD5_GPIO35);
+PINCTRL_MUX(GPIO36, 0, &PAD6_GPIO36);
+PINCTRL_MUX(GPIO37, 0, &PAD11_GPIO37);
+PINCTRL_MUX(GPIO38, 0, &PAD12_GPIO38);
+PINCTRL_MUX(GPIO39, 0, &PAD9_GPIO39);
+PINCTRL_MUX(GPIO40, 0, &PAD10_GPIO40);
+PINCTRL_MUX(GPIO41, 0, &PAD13_GPIO41);
+PINCTRL_MUX(GPIO42, 0, &PAD14_GPIO42);
+PINCTRL_MUX(GPIO43, 0, &PAD16_GPIO43);
+PINCTRL_MUX(GPIO44, 0, &PAD17_GPIO44);
+PINCTRL_MUX(GPIO45, 0, &PAD18_GPIO45);
+PINCTRL_MUX(GPIO46, 0, &PAD19_GPIO46);
+PINCTRL_MUX(GPIO47, 0, &PAD15_GPIO47);
+PINCTRL_MUX(GPIO48, 0, &PAD20_GPIO48);
+PINCTRL_MUX(GPIO49, 0, &PAD22_GPIO49);
+PINCTRL_MUX(GPIO50, 0, &PAD23_GPIO50);
+PINCTRL_MUX(GPIO51, 0, &PAD24_GPIO51);
+PINCTRL_MUX(GPIO52, 0, &PAD25_GPIO52);
+PINCTRL_MUX(GPIO53, 0, &PAD26_GPIO53);
+PINCTRL_MUX(GPIO54, 0, &PAD27_GPIO54);
+PINCTRL_MUX(GPIO55, 0, &PAD28_GPIO55);
+PINCTRL_MUX(GPIO56, 0, &PAD29_GPIO56);
+PINCTRL_MUX(GPIO57, 0, &PAD30_GPIO57);
+PINCTRL_MUX(GPIO58, 0, &PAD31_GPIO58);
+PINCTRL_MUX(GPIO59, 0, &PAD32_GPIO59);
+PINCTRL_MUX(GPIO60, 0, &PAD33_GPIO60);
+PINCTRL_MUX(GPIO61, 0, &PAD34_GPIO61);
+PINCTRL_MUX(GPIO62, 0, &PAD35_GPIO62);
+PINCTRL_MUX(GPIO63, 0, &PAD36_GPIO63);
+
+PINCTRL_MUX(SD1_CLK_EMMC, 3, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP_EMMC, 3, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0_EMMC, 3, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1_EMMC, 3, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2_EMMC, 3, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3_EMMC, 3, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+/* PINCTRL_DEVICE */
+PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO,
+ &MUX_AC_I2S_WS, &MUX_AC_MCLK);
+PINCTRL_DEVICE(AC_MCLK, 1, &MUX_AC_MCLK);
+PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI,
+ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN);
+PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI,
+ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN);
+PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO,
+ &MUX_DW_I2S_WS);
+PINCTRL_DEVICE(ETH, 2, &MUX_ETH_LINK_ACT, &MUX_ETH_LINK_STA);
+PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA);
+PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA);
+PINCTRL_DEVICE(I2C2, 2, &MUX_I2C2_SCL, &MUX_I2C2_SDA);
+PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI,
+ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN);
+PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0);
+PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1);
+PINCTRL_DEVICE(PWM10, 1, &MUX_PWM10);
+PINCTRL_DEVICE(PWM11, 1, &MUX_PWM11);
+PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2);
+PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3);
+PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4);
+PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5);
+PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6);
+PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7);
+PINCTRL_DEVICE(PWM8, 1, &MUX_PWM8);
+PINCTRL_DEVICE(PWM9, 1, &MUX_PWM9);
+PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK,
+ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1,
+ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN);
+PINCTRL_DEVICE(RTC, 1, &MUX_RTC_CLK);
+PINCTRL_DEVICE(SADC_XAIN0, 1, &MUX_SADC_XAIN0);
+PINCTRL_DEVICE(SADC_XAIN1, 1, &MUX_SADC_XAIN1);
+PINCTRL_DEVICE(SADC_XAIN2, 1, &MUX_SADC_XAIN2);
+PINCTRL_DEVICE(SADC_XAIN3, 1, &MUX_SADC_XAIN3);
+PINCTRL_DEVICE(SD0, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0);
+PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_WIFI, 6, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, &MUX_SD0_DATA_0,
+ &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD1, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_1BIT_NO_WP, 4, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0);
+PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_WIFI, 6, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, &MUX_SD1_DATA_0,
+ &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SENSOR_CLK, 1, &MUX_SENSOR_CLK);
+PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_RXD,
+ &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_D2,
+ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI1, 4, &MUX_GPIO14, &MUX_SSI1_CLK, &MUX_SSI1_RXD,
+ &MUX_SSI1_TXD);
+PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN_0, &MUX_SSI2_RXD,
+ &MUX_SSI2_TXD);
+PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX);
+PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX);
+PINCTRL_DEVICE(UART2, 2, &MUX_UART2_RX, &MUX_UART2_TX);
+PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN);
+PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0);
+PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1);
+PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2);
+PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3);
+PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4);
+PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5);
+PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6);
+PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7);
+PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8);
+PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9);
+PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10);
+PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11);
+PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12);
+PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13);
+PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14);
+PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15);
+PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16);
+PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17);
+PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18);
+PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19);
+PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20);
+PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21);
+PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22);
+PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23);
+PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24);
+PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25);
+PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26);
+PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27);
+PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28);
+PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29);
+PINCTRL_DEVICE(GPIO30, 1, &MUX_GPIO30);
+PINCTRL_DEVICE(GPIO31, 1, &MUX_GPIO31);
+PINCTRL_DEVICE(GPIO32, 1, &MUX_GPIO32);
+PINCTRL_DEVICE(GPIO33, 1, &MUX_GPIO33);
+PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34);
+PINCTRL_DEVICE(GPIO35, 1, &MUX_GPIO35);
+PINCTRL_DEVICE(GPIO36, 1, &MUX_GPIO36);
+PINCTRL_DEVICE(GPIO37, 1, &MUX_GPIO37);
+PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38);
+PINCTRL_DEVICE(GPIO39, 1, &MUX_GPIO39);
+PINCTRL_DEVICE(GPIO40, 1, &MUX_GPIO40);
+PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41);
+PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42);
+PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43);
+PINCTRL_DEVICE(GPIO44, 1, &MUX_GPIO44);
+PINCTRL_DEVICE(GPIO45, 1, &MUX_GPIO45);
+PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46);
+PINCTRL_DEVICE(GPIO47, 1, &MUX_GPIO47);
+PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48);
+PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49);
+PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50);
+PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51);
+PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52);
+PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53);
+PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54);
+PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55);
+PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56);
+PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57);
+PINCTRL_DEVICE(GPIO58, 1, &MUX_GPIO58);
+PINCTRL_DEVICE(GPIO59, 1, &MUX_GPIO59);
+PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60);
+PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61);
+PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62);
+PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63);
+
+PINCTRL_DEVICE(SD1_EMMC, 6, &MUX_SD1_CLK_EMMC, &MUX_SD1_CMD_RSP_EMMC,
+ &MUX_SD1_DATA_0_EMMC, &MUX_SD1_DATA_1_EMMC, &MUX_SD1_DATA_2_EMMC,
+ &MUX_SD1_DATA_3_EMMC);
+
+void fh_pinctrl_init_devicelist(OS_LIST *list)
+{
+ OS_LIST_EMPTY(list);
+
+ /*PINCTRL_ADD_DEVICE*/
+ PINCTRL_ADD_DEVICE(ACI2S);
+ PINCTRL_ADD_DEVICE(AC_MCLK);
+ PINCTRL_ADD_DEVICE(ARCJTAG);
+ PINCTRL_ADD_DEVICE(ARMJTAG);
+ PINCTRL_ADD_DEVICE(DWI2S);
+ PINCTRL_ADD_DEVICE(ETH);
+ PINCTRL_ADD_DEVICE(I2C0);
+ PINCTRL_ADD_DEVICE(I2C1);
+ PINCTRL_ADD_DEVICE(I2C2);
+ PINCTRL_ADD_DEVICE(PAEJTAG);
+ PINCTRL_ADD_DEVICE(PWM0);
+ PINCTRL_ADD_DEVICE(PWM1);
+ PINCTRL_ADD_DEVICE(PWM10);
+ PINCTRL_ADD_DEVICE(PWM11);
+ PINCTRL_ADD_DEVICE(PWM2);
+ PINCTRL_ADD_DEVICE(PWM3);
+ PINCTRL_ADD_DEVICE(PWM4);
+ PINCTRL_ADD_DEVICE(PWM5);
+ PINCTRL_ADD_DEVICE(PWM6);
+ PINCTRL_ADD_DEVICE(PWM7);
+ PINCTRL_ADD_DEVICE(PWM8);
+ PINCTRL_ADD_DEVICE(PWM9);
+ PINCTRL_ADD_DEVICE(RMII);
+ PINCTRL_ADD_DEVICE(RTC);
+ PINCTRL_ADD_DEVICE(SADC_XAIN0);
+ PINCTRL_ADD_DEVICE(SADC_XAIN1);
+ PINCTRL_ADD_DEVICE(SADC_XAIN2);
+ PINCTRL_ADD_DEVICE(SADC_XAIN3);
+ PINCTRL_ADD_DEVICE(SD0);
+ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_WIFI);
+ PINCTRL_ADD_DEVICE(SD1);
+ PINCTRL_ADD_DEVICE(SD1_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_WIFI);
+ PINCTRL_ADD_DEVICE(SENSOR_CLK);
+ PINCTRL_ADD_DEVICE(SSI0);
+ PINCTRL_ADD_DEVICE(SSI0_4BIT);
+ PINCTRL_ADD_DEVICE(SSI1);
+ PINCTRL_ADD_DEVICE(SSI2);
+ PINCTRL_ADD_DEVICE(UART0);
+ PINCTRL_ADD_DEVICE(UART1);
+ PINCTRL_ADD_DEVICE(UART2);
+ PINCTRL_ADD_DEVICE(USB);
+ PINCTRL_ADD_DEVICE(GPIO0);
+ PINCTRL_ADD_DEVICE(GPIO1);
+ PINCTRL_ADD_DEVICE(GPIO2);
+ PINCTRL_ADD_DEVICE(GPIO3);
+ PINCTRL_ADD_DEVICE(GPIO4);
+ PINCTRL_ADD_DEVICE(GPIO5);
+ PINCTRL_ADD_DEVICE(GPIO6);
+ PINCTRL_ADD_DEVICE(GPIO7);
+ PINCTRL_ADD_DEVICE(GPIO8);
+ PINCTRL_ADD_DEVICE(GPIO9);
+ PINCTRL_ADD_DEVICE(GPIO10);
+ PINCTRL_ADD_DEVICE(GPIO11);
+ PINCTRL_ADD_DEVICE(GPIO12);
+ PINCTRL_ADD_DEVICE(GPIO13);
+ PINCTRL_ADD_DEVICE(GPIO14);
+ PINCTRL_ADD_DEVICE(GPIO15);
+ PINCTRL_ADD_DEVICE(GPIO16);
+ PINCTRL_ADD_DEVICE(GPIO17);
+ PINCTRL_ADD_DEVICE(GPIO18);
+ PINCTRL_ADD_DEVICE(GPIO19);
+ PINCTRL_ADD_DEVICE(GPIO20);
+ PINCTRL_ADD_DEVICE(GPIO21);
+ PINCTRL_ADD_DEVICE(GPIO22);
+ PINCTRL_ADD_DEVICE(GPIO23);
+ PINCTRL_ADD_DEVICE(GPIO24);
+ PINCTRL_ADD_DEVICE(GPIO25);
+ PINCTRL_ADD_DEVICE(GPIO26);
+ PINCTRL_ADD_DEVICE(GPIO27);
+ PINCTRL_ADD_DEVICE(GPIO28);
+ PINCTRL_ADD_DEVICE(GPIO29);
+ PINCTRL_ADD_DEVICE(GPIO30);
+ PINCTRL_ADD_DEVICE(GPIO31);
+ PINCTRL_ADD_DEVICE(GPIO32);
+ PINCTRL_ADD_DEVICE(GPIO33);
+ PINCTRL_ADD_DEVICE(GPIO34);
+ PINCTRL_ADD_DEVICE(GPIO35);
+ PINCTRL_ADD_DEVICE(GPIO36);
+ PINCTRL_ADD_DEVICE(GPIO37);
+ PINCTRL_ADD_DEVICE(GPIO38);
+ PINCTRL_ADD_DEVICE(GPIO39);
+ PINCTRL_ADD_DEVICE(GPIO40);
+ PINCTRL_ADD_DEVICE(GPIO41);
+ PINCTRL_ADD_DEVICE(GPIO42);
+ PINCTRL_ADD_DEVICE(GPIO43);
+ PINCTRL_ADD_DEVICE(GPIO44);
+ PINCTRL_ADD_DEVICE(GPIO45);
+ PINCTRL_ADD_DEVICE(GPIO46);
+ PINCTRL_ADD_DEVICE(GPIO47);
+ PINCTRL_ADD_DEVICE(GPIO48);
+ PINCTRL_ADD_DEVICE(GPIO49);
+ PINCTRL_ADD_DEVICE(GPIO50);
+ PINCTRL_ADD_DEVICE(GPIO51);
+ PINCTRL_ADD_DEVICE(GPIO52);
+ PINCTRL_ADD_DEVICE(GPIO53);
+ PINCTRL_ADD_DEVICE(GPIO54);
+ PINCTRL_ADD_DEVICE(GPIO55);
+ PINCTRL_ADD_DEVICE(GPIO56);
+ PINCTRL_ADD_DEVICE(GPIO57);
+ PINCTRL_ADD_DEVICE(GPIO58);
+ PINCTRL_ADD_DEVICE(GPIO59);
+ PINCTRL_ADD_DEVICE(GPIO60);
+ PINCTRL_ADD_DEVICE(GPIO61);
+ PINCTRL_ADD_DEVICE(GPIO62);
+ PINCTRL_ADD_DEVICE(GPIO63);
+
+ PINCTRL_ADD_DEVICE(SD1_EMMC);
+}
+
+char *fh_pinctrl_selected_devices[] =
+{
+ CONFIG_PINCTRL_SELECT
+};
diff --git a/arch/arm/mach-fh/fh8858v200/Makefile b/arch/arm/mach-fh/fh8858v200/Makefile
new file mode 100644
index 00000000..1443fdae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v200/Makefile
@@ -0,0 +1 @@
+obj-y += board.o chip.o
\ No newline at end of file
diff --git a/arch/arm/mach-fh/fh8858v200/board.c b/arch/arm/mach-fh/fh8858v200/board.c
new file mode 100644
index 00000000..f6be0a53
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v200/board.c
@@ -0,0 +1,1123 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/phy.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/eeprom.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/if_alg.h>
+#include <linux/mmc/host.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/io.h>
+#include <mach/board_config.h>
+#include <mach/pinctrl.h>
+#include <mach/clock.h>
+#include <mach/fh_uart_plat.h>
+#include <mach/fh_mci_plat.h>
+#include <mach/fh_gmac_plat.h>
+#include <mach/fh_gpio_plat.h>
+#include <mach/fh_efuse_plat.h>
+#include <mach/fh_dma_plat.h>
+#include <mach/fh_spi_plat.h>
+#include <mach/fh_i2s_plat.h>
+#include <mach/fh_pwm_plat.h>
+#include <mach/fh_wdt_plat.h>
+#include <mach/fh_usb_plat.h>
+#include <mach/fh_sadc_plat.h>
+#include <mach/fh_rtc_plat.h>
+#include "chip.h"
+
+struct uart_port fh_serial_ports[FH_UART_NUMBER];
+
+static struct map_desc fh8858v200_io_desc[] = {
+ {
+ .virtual = VA_RAM_REG_BASE,
+ .pfn = __phys_to_pfn(RAM_BASE),
+ .length = SZ_16K,
+ .type = MT_MEMORY_RWX,
+ },
+ {
+ .virtual = VA_DDRC_REG_BASE,
+ .pfn = __phys_to_pfn(DDRC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_INTC_REG_BASE,
+ .pfn = __phys_to_pfn(INTC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_TIMER_REG_BASE,
+ .pfn = __phys_to_pfn(TIMER_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_PMU_REG_BASE,
+ .pfn = __phys_to_pfn(PMU_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART0_REG_BASE,
+ .pfn = __phys_to_pfn(UART0_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART1_REG_BASE,
+ .pfn = __phys_to_pfn(UART1_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART2_REG_BASE,
+ .pfn = __phys_to_pfn(UART2_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+
+};
+
+static struct resource fh_gpio0_resources[] = {
+ {
+ .start = GPIO0_REG_BASE,
+ .end = GPIO0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO0_IRQ,
+ .end = GPIO0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gpio1_resources[] = {
+ {
+ .start = GPIO1_REG_BASE,
+ .end = GPIO1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO1_IRQ,
+ .end = GPIO1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart0_resources[] = {
+ {
+ .start = (UART0_REG_BASE),
+ .end = (UART0_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = UART0_IRQ,
+ .end = UART0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart1_resources[] = {
+ {
+ .start = (UART1_REG_BASE),
+ .end = (UART1_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART1_IRQ,
+ .end = UART1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_uart2_resources[] = {
+ {
+ .start = (UART2_REG_BASE),
+ .end = (UART2_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART2_IRQ,
+ .end = UART2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+static struct resource fh_sdc0_resources[] = {
+ {
+ .start = SDC0_REG_BASE,
+ .end = SDC0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC0_IRQ,
+ .end = SDC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_sdc1_resources[] = {
+ {
+ .start = SDC1_REG_BASE,
+ .end = SDC1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC1_IRQ,
+ .end = SDC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gmac_resources[] = {
+ {
+ .start = GMAC_REG_BASE,
+ .end = GMAC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GMAC_IRQ,
+ .end = GMAC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource fh_wdt_resources[] = {
+ {
+ .start = WDT_REG_BASE,
+ .end = WDT_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = WDT_IRQ,
+ .end = WDT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct resource fh_perf_resources[] = {
+ {
+ .start = PMU_REG_BASE,
+ .end = PMU_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PERF_IRQ,
+ .end = PERF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+
+static struct fh_gmac_platform_data fh_gmac_data = {
+ .phy_reset_pin = 29,
+};
+
+static struct fh_uart_dma uart1_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART1_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART1_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART1_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART1_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+static struct fh_uart_dma uart2_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART2_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART2_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART2_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART2_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+
+static struct fh_platform_uart fh_uart_platform_data[] = {
+ {
+ .mapbase = UART0_REG_BASE,
+ .fifo_size = 16,
+ .irq = UART0_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = NULL,
+ },
+ {
+ .mapbase = UART1_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART1_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart1_dma_info,
+ },
+ {
+ .mapbase = UART2_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART2_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart2_dma_info,
+ },
+};
+
+static struct resource fh_pwm_resources[] = {
+ {
+ .start = PWM_REG_BASE,
+ .end = PWM_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PWM_IRQ,
+ .end = PWM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_i2c_resources_0[] = {
+ {
+ .start = I2C0_REG_BASE,
+ .end = I2C0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C0_IRQ,
+ .end = I2C0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_1[] = {
+ {
+ .start = I2C1_REG_BASE,
+ .end = I2C1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C1_IRQ,
+ .end = I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_2[] = {
+ {
+ .start = I2C2_REG_BASE,
+ .end = I2C2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C2_IRQ,
+ .end = I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_rtc_resources[] = {
+ {
+ .start = RTC_REG_BASE,
+ .end = RTC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio0_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO0",
+ .base = 0,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio1_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO1",
+ .base = 32,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_pwm_data pwm_data = {
+ .npwm = 12,
+};
+
+static struct resource fh_sadc_resources[] = {
+ {
+ .start = SADC_REG_BASE,
+ .end = SADC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SADC_IRQ,
+ .end = SADC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_aes_resources[] = {
+ {
+ .start = AES_REG_BASE,
+ .end = AES_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = AES_IRQ,
+ .end = AES_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_efuse_resources[] = {
+ {
+ .start = EFUSE_REG_BASE,
+ .end = EFUSE_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+
+static struct resource fh_axi_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+
+static struct resource fh_spi0_resources[] = {
+ {
+ .start = SPI0_REG_BASE,
+ .end = SPI0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI0_IRQ,
+ .end = SPI0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi1_resources[] = {
+ {
+ .start = SPI1_REG_BASE,
+ .end = SPI1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI1_IRQ,
+ .end = SPI1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi2_resources[] = {
+ {
+ .start = SPI2_REG_BASE,
+ .end = SPI2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "fh spi2 mem",
+ },
+ {
+ .start = SPI2_IRQ,
+ .end = SPI2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ .name = "fh spi2 irq",
+ },
+};
+
+static struct resource fh_usb_resources[] = {
+ {
+ .start = USBC_REG_BASE,
+ .end = USBC_REG_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USBC_IRQ,
+ .end = USBC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static unsigned int fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+
+struct fh_mci_board fh_mci = {
+ .num_slots = 1,
+ .get_cd = fh_mci_sys_card_detect_fixed,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+ .rescan_max_num = 2,
+};
+
+struct fh_mci_board fh_mci_sd = {
+ .num_slots = 1,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+};
+
+static struct platform_device fh_gmac_device = {
+ .name = "fh_gmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gmac_resources),
+ .resource = fh_gmac_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_gmac_data,
+ },
+};
+
+struct platform_device fh_sd0_device = {
+ .name = "fh_mci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sdc0_resources),
+ .resource = fh_sdc0_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci_sd,
+ }
+};
+
+struct platform_device fh_sd1_device = {
+ .name = "fh_mci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_sdc1_resources),
+ .resource = fh_sdc1_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci,
+ }
+};
+
+struct fh_sadc_platform_data fh_sadc_data = {
+ .ref_vol = 1800,
+ .active_bit = 0xfff,
+};
+
+static struct platform_device fh_sadc_device = {
+ .name = "fh_sadc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sadc_resources),
+ .resource = fh_sadc_resources,
+ .dev = {
+ .platform_data = &fh_sadc_data,
+ },
+};
+
+static struct platform_device fh_uart0_device = {
+ .name = "ttyS",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_uart0_resources),
+ .resource = fh_uart0_resources,
+ .dev.platform_data = &fh_uart_platform_data[0],
+};
+
+static struct platform_device fh_uart1_device = {
+ .name = "ttyS",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_uart1_resources),
+ .resource = fh_uart1_resources,
+ .dev.platform_data = &fh_uart_platform_data[1],
+};
+
+static struct platform_device fh_uart2_device = {
+ .name = "ttyS",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_uart2_resources),
+ .resource = fh_uart2_resources,
+ .dev.platform_data = &fh_uart_platform_data[2],
+};
+
+static struct platform_device fh_pinctrl_device = {
+ .name = "fh_pinctrl",
+ .id = 0,
+};
+
+static struct platform_device fh_i2c0_device = {
+ .name = "fh_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_0),
+ .resource = fh_i2c_resources_0,
+};
+
+static struct platform_device fh_i2c1_device = {
+ .name = "fh_i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_1),
+ .resource = fh_i2c_resources_1,
+};
+
+static struct platform_device fh_i2c2_device = {
+ .name = "fh_i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_2),
+ .resource = fh_i2c_resources_2,
+};
+
+static struct fh_rtc_plat_data rtc_plat_data[] = {
+ {
+ .lut_cof = 58,
+ .lut_offset = 0xff,
+ .tsensor_cp_default_out = 0x993,
+ .clk_name = "rtc_hclk_gate",
+ },
+ {
+ .lut_cof = 71,
+ .lut_offset = 0xf6,
+ .tsensor_cp_default_out = 0x9cc,
+ .clk_name = "rtc_hclk_gate",
+ }
+};
+
+static struct platform_device fh_rtc_device = {
+ .name = "fh_rtc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_rtc_resources),
+ .resource = fh_rtc_resources,
+ .dev.platform_data = &rtc_plat_data[0],
+};
+
+static struct resource fh_i2s_resources[] = {
+ {
+ .start = I2S_REG_BASE,
+ .end = I2S_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ACW_REG_BASE,
+ .end = ACW_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = I2S0_IRQ,
+ .end = I2S0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_i2s_platform_data fh_i2s_data = {
+ .dma_capture_channel = 4,
+ .dma_playback_channel = 5,
+ .dma_master = 0,
+ .dma_rx_hs_num = 10,
+ .dma_tx_hs_num = 11,
+ .clk = "i2s_clk",
+ .acodec_mclk = "ac_clk",
+};
+
+static struct platform_device fh_i2s_device = {
+ .name = "fh_audio",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2s_resources),
+ .resource = fh_i2s_resources,
+ .dev = {
+ .platform_data = &fh_i2s_data,
+ },
+};
+
+static struct platform_device fh_gpio0_device = {
+ .name = GPIO_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gpio0_resources),
+ .resource = fh_gpio0_resources,
+ .dev = {
+ .platform_data = &fh_gpio0_chip,
+ },
+};
+
+static struct platform_device fh_gpio1_device = {
+ .name = GPIO_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_gpio1_resources),
+ .resource = fh_gpio1_resources,
+ .dev = {
+ .platform_data = &fh_gpio1_chip,
+ },
+};
+
+static struct platform_device fh_aes_device = {
+ .name = "fh_aes",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_aes_resources),
+ .resource = fh_aes_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+struct fh_efuse_platform_data fh_efuse_plat_data = {
+ .efuse_support_flag = CRYPTO_CPU_SET_KEY |
+ CRYPTO_EX_MEM_SET_KEY |
+ CRYPTO_EX_MEM_SWITCH_KEY |
+ CRYPTO_EX_MEM_4_ENTRY_1_KEY |
+ CRYPTO_EX_MEM_INDEP_POWER,
+};
+
+
+
+#define FH_SPI0_CS0 (6)
+#define FH_SPI0_CS1 (55)
+
+#define FH_SPI1_CS0 (14)
+#define FH_SPI1_CS1 (57)
+
+#define SPI0_FIFO_DEPTH (128)
+#define SPI0_CLK_IN (200000000)
+#define SPI0_MAX_SLAVE_NO (2)
+#define SPI0_DMA_RX_CHANNEL (0)
+#define SPI0_DMA_TX_CHANNEL (1)
+
+#define SPI1_FIFO_DEPTH (64)
+#define SPI1_CLK_IN (100000000)
+#define SPI1_MAX_SLAVE_NO (2)
+#define SPI1_DMA_RX_CHANNEL (2)
+#define SPI1_DMA_TX_CHANNEL (3)
+
+#define SPI2_CLK_IN (100000000)
+
+/* SPI_TRANSFER_USE_DMA */
+static struct fh_spi_platform_data fh_spi0_data = {
+ .bus_no = 0,
+ .apb_clock_in = SPI0_CLK_IN,
+ .clock_source = {100000000, 150000000, 200000000},
+ .clock_source_num = 3,
+ .slave_max_num = SPI0_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI0_CS0,
+ .cs_data[0].name = "spi0_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI0_CS1,
+ .cs_data[1].name = "spi0_cs1",
+ .clk_name = "spi0_clk",
+ .dma_transfer_enable = SPI_TRANSFER_USE_DMA,
+ .rx_dma_channel = SPI0_DMA_RX_CHANNEL,
+ .rx_handshake_num = 4,
+ /*dma use inc mode could move data by burst mode...*/
+ /*or move data use single mode with low efficient*/
+ .ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |
+ MULTI_WIRE_SUPPORT,
+};
+
+static struct fh_spi_platform_data fh_spi1_data = {
+ .bus_no = 1,
+ .apb_clock_in = SPI1_CLK_IN,
+ .clock_source = {SPI1_CLK_IN},
+ .clock_source_num = 1,
+ .slave_max_num = SPI1_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI1_CS0,
+ .cs_data[0].name = "spi1_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI1_CS1,
+ .cs_data[1].name = "spi1_cs1",
+ .clk_name = "spi1_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct fh_spi_platform_data fh_spi2_data = {
+ .apb_clock_in = SPI2_CLK_IN,
+ .dma_transfer_enable = 0,
+ .rx_handshake_num = 12,
+ .clk_name = "spi2_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct platform_device fh_efuse_device = {
+ .name = "fh_efuse",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_efuse_resources),
+ .resource = fh_efuse_resources,
+ .dev = {
+ .platform_data = &fh_efuse_plat_data,
+ },
+};
+
+struct fh_axi_dma_platform_data axi_dma_plat_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_axi_dma_device = {
+ .name = "fh_axi_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_axi_dma_resources),
+ .resource = fh_axi_dma_resources,
+ .dev = {
+ .platform_data = &axi_dma_plat_data,
+ },
+};
+
+static struct platform_device fh_spi0_device = {
+ .name = "fh_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi0_resources),
+ .resource = fh_spi0_resources,
+ .dev = {
+ .platform_data = &fh_spi0_data,
+ },
+};
+
+static struct platform_device fh_spi1_device = {
+ .name = "fh_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_spi1_resources),
+ .resource = fh_spi1_resources,
+ .dev = {
+ .platform_data = &fh_spi1_data,
+ },
+};
+
+static struct platform_device fh_spi2_device = {
+ .name = "fh_spi_slave",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi2_resources),
+ .resource = fh_spi2_resources,
+ .dev = {
+ .platform_data = &fh_spi2_data,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct platform_device fh_perf_device = {
+ .name = "fh_perf_mon",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_perf_resources),
+ .resource = fh_perf_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+
+static struct fh_wdt_platform_data fh_wdt_data = {
+ .mode = MODE_DISCRETE,
+};
+
+struct platform_device fh_wdt_device = {
+ .name = "fh_wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_wdt_resources),
+ .resource = fh_wdt_resources,
+ .dev = {
+ .platform_data = &fh_wdt_data,
+ }
+};
+
+static struct platform_device fh_pwm_device = {
+ .name = "fh_pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_pwm_resources),
+ .resource = fh_pwm_resources,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
+};
+
+static struct fh_usb_platform_data fh_usb_data = {
+ .dr_mode = "host",
+ .vbus_pwren = 47,
+};
+
+struct platform_device fh_usb_device = {
+ .name = "fh_usb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_usb_resources),
+ .resource = fh_usb_resources,
+ .dev = {
+ .platform_data = &fh_usb_data,
+ }
+};
+
+#ifdef CONFIG_FH_TSENSOR
+struct platform_device fh_tsensor_device = {
+ .name = "fh_tsensor",
+ .id = 0,
+};
+#endif
+
+static struct platform_device *fh8858v200_devices[] __initdata = {
+ &fh_uart0_device,
+ &fh_uart1_device,
+ &fh_uart2_device,
+ &fh_pinctrl_device,
+ &fh_i2c0_device,
+ &fh_i2c1_device,
+ &fh_i2c2_device,
+ &fh_rtc_device,
+ &fh_sd0_device,
+ &fh_sd1_device,
+ &fh_sadc_device,
+ &fh_gmac_device,
+ &fh_gpio0_device,
+ &fh_gpio1_device,
+ &fh_aes_device,
+ &fh_efuse_device,
+ &fh_axi_dma_device,
+ &fh_spi0_device,
+ &fh_spi1_device,
+ &fh_spi2_device,
+ &fh_i2s_device,
+ &fh_pwm_device,
+ &fh_wdt_device,
+ &fh_usb_device,
+#ifdef CONFIG_FH_PERF_MON
+ &fh_perf_device,
+#endif
+#ifdef CONFIG_FH_TSENSOR
+ &fh_tsensor_device,
+#endif
+};
+
+static struct mtd_partition fh_sf_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* Ramboot & U-Boot environment */
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* U-Boot */
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi_flash:256k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),4M(kernel),
+ * 8M(rootfs),
+ * -(app) */
+ /* two blocks with bad block table (and mirror) at the end */
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct mtd_partition fh_sf_nand_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_512K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi0.0:64k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),
+ * 4M(kernel),
+ * 8M(rootfs),
+ * -(app)
+ * two blocks with bad block table (and mirror) at the end
+ */
+};
+#endif
+
+static struct flash_platform_data fh_flash_platform_data = {
+ .name = "spi_flash",
+ .parts = fh_sf_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_parts),
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct flash_platform_data fh_nandflash_platform_data = {
+ .name = "spi_nandflash",
+ .parts = fh_sf_nand_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_nand_parts),
+};
+#endif
+
+static struct spi_board_info fh_spi_devices[] = {
+#ifdef CONFIG_MTD_SPI_NAND
+ {
+ .modalias = "spi-nand",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &fh_nandflash_platform_data,
+ },
+#endif
+ {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ /* multi wire should adapt spi para 'ctl_wire_support'*/
+ .mode = SPI_MODE_3 | SPI_RX_DUAL,
+ .max_speed_hz = 50000000,
+ .platform_data = &fh_flash_platform_data,
+ },
+
+};
+
+extern void early_print(const char *str, ...);
+
+static void __init fh_console_pre_init(struct fh_platform_uart *plat, int num)
+{
+ int idx = 0;
+
+ for (; idx < num; idx++) {
+ struct uart_port *port;
+
+ port = &fh_serial_ports[idx];
+ port->mapbase = plat[idx].mapbase;
+ port->fifosize = plat[idx].fifo_size;
+ port->uartclk = plat[idx].uartclk;
+
+ switch (idx) {
+ case 0:
+ port->membase = (unsigned char *)VA_UART0_REG_BASE;
+ break;
+ case 1:
+ port->membase = (unsigned char *)VA_UART1_REG_BASE;
+ break;
+ case 2:
+ port->membase = (unsigned char *)VA_UART2_REG_BASE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void __init fh8858v200_map_io(void)
+{
+ iotable_init(fh8858v200_io_desc, ARRAY_SIZE(fh8858v200_io_desc));
+ fh_console_pre_init(fh_uart_platform_data,
+ ARRAY_SIZE(fh_uart_platform_data));
+}
+
+
+static __init void fh8858v200_board_init(void)
+{
+ if (fh_is_8858v210())
+ fh_rtc_device.dev.platform_data = &rtc_plat_data[1];
+ platform_add_devices(fh8858v200_devices,
+ ARRAY_SIZE(fh8858v200_devices));
+ spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices));
+}
+void __init fh_timer_init_no_of(unsigned int iovbase,
+ unsigned int irqno);
+
+static void __init fh8858v200_init_early(void)
+{
+ fh_pmu_init();
+ fh_pinctrl_init(VA_PMU_REG_BASE + 0x80);
+}
+
+static void __init fh_time_init(void)
+{
+ unsigned int vtimerbase = (unsigned int)ioremap(TIMER_REG_BASE, SZ_4K);
+
+ fh_clk_init();
+ fh_timer_init_no_of(vtimerbase, TMR0_IRQ);
+
+}
+
+void __init fh_intc_init_no_of(unsigned int iovbase);
+static void __init fh_intc_init(void)
+{
+ unsigned int vintcbase = (unsigned int)ioremap(INTC_REG_BASE, SZ_4K);
+
+ fh_intc_init_no_of(vintcbase);
+
+}
+static void fh8858v200_restart
+ (enum reboot_mode mode, const char *cmd)
+{
+ fh_pmu_restart();
+}
+
+
+MACHINE_START(FH8858V200, "FH8858V200")
+ .atag_offset = 0x100,
+ .map_io = fh8858v200_map_io,
+ .init_irq = fh_intc_init,
+ .init_time = fh_time_init,
+ .init_machine = fh8858v200_board_init,
+ .init_early = fh8858v200_init_early,
+ .restart = fh8858v200_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-fh/fh8858v200/board_config.fh8858v200.appboard b/arch/arm/mach-fh/fh8858v200/board_config.fh8858v200.appboard
new file mode 100644
index 00000000..335a1304
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v200/board_config.fh8858v200.appboard
@@ -0,0 +1,45 @@
+#ifndef BOARD_CONFIG_H_
+#define BOARD_CONFIG_H_
+
+/*
+ * GPIO0 -> IRCUT_ON
+ * GPIO1 -> IRCUT_OFF
+ * GPIO2 -> USB_PWREN
+ * GPIO11 -> EMAC PHY Reset
+ * GPIO12 -> CIS_CLK
+ * GPIO13 -> CIS_RSTN
+ * GPIO14 -> CIS_PDN
+ * GPIO19 -> SD1_PWREN/WIFI_REG_ON
+ * GPIO20 -> AK7755 Reset
+ * GPIO24 -> LED0
+ * GPIO25 -> LED1
+ * GPIO26 -> Reset Configs
+ * GPIO27 -> AK7755 PowerDown
+ * GPIO28 -> IR
+ * GPIO53 -> USB_PWREN/SD0_PWREN
+ * GPIO55 -> SD1 WIFI Interrupt
+ */
+
+#define CONFIG_SD_CD_FIXED
+
+#define CONFIG_ISP_CLK_RATE 200000000
+#define CONFIG_JPEG_CLK_RATE 200000000
+#define CONFIG_VEU_CLK_RATE 300000000
+
+#define USB_VBUS_PWR_GPIO (47)
+
+#define ETH_GPIO "ETH", "GPIO48", "GPIO49", "GPIO50", "GPIO51", "GPIO52",\
+ "GPIO53", "GPIO54", "GPIO55", "GPIO56"
+
+#define CONFIG_PINCTRL_SELECT \
+ "I2C0", "PWM2", "PWM3", "PWM4", "PWM5", "PWM6", "PWM7", \
+ "PWM8", "PWM9", "SADC_XAIN0", "SADC_XAIN1", \
+ "SADC_XAIN2", "SADC_XAIN3", "SD0_NO_WP", "SD1_NO_WP", \
+ "SENSOR_CLK", "SSI0_4BIT", "UART0", "UART1", "GPIO4", \
+ "GPIO13", "GPIO14", "GPIO15", ETH_GPIO, \
+ "GPIO30", "GPIO31", "GPIO32", "GPIO43", "GPIO44", \
+ "GPIO47", \
+\
+ "GPIO11", "GPIO16", "GPIO45", "GPIO46"
+
+#endif /* BOARD_CONFIG_H_ */
diff --git a/arch/arm/mach-fh/fh8858v200/chip.c b/arch/arm/mach-fh/fh8858v200/chip.c
new file mode 100644
index 00000000..9bbb3c49
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v200/chip.c
@@ -0,0 +1,747 @@
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/clock.h>
+#include <mach/board_config.h>
+
+/*
+ * external oscillator
+ * fixed to 24M
+ */
+static struct fh_clk osc_clk = {
+ .name = "osc_clk",
+ .frequency = OSC_FREQUENCY,
+ .flag = CLOCK_FIXED,
+};
+
+/*
+ * phase-locked-loop device,
+ * generates a higher frequency clock
+ * from the external oscillator reference
+ *PLL_DDR
+ */
+
+static struct fh_clk pll_ddr_rclk = {
+ .name = "pll_ddr_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL0,
+ .en_reg_offset = REG_PMU_PLL0_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_CPU*/
+static struct fh_clk pll_cpu_pclk = {
+ .name = "pll_cpu_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+static struct fh_clk pll_cpu_rclk = {
+ .name = "pll_cpu_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_SYS*/
+static struct fh_clk pll_sys_pclk = {
+ .name = "pll_sys_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+
+static struct fh_clk pll_sys_rclk = {
+ .name = "pll_sys_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+static struct fh_clk pllsysp_div12_clk = {
+ .name = "pllsysp_div12_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk ddr_clk = {
+ .name = "ddr_clk",
+ .flag = CLOCK_NODIV,
+ .parent = {&pll_ddr_rclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8,
+};
+static struct fh_clk arm_clk = {
+ .name = "arm_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NOGATE|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1,
+};
+static struct fh_clk arc_clk = {
+ .name = "arc_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400000,
+};
+static struct fh_clk ahb_clk = {
+ .name = "ahb_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&osc_clk, &pll_sys_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf0000,
+};
+
+static struct fh_clk isp_aclk = {
+ .name = "isp_aclk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1,
+ .def_rate = CONFIG_ISP_CLK_RATE,
+};
+static struct fh_clk ispb_aclk = {
+ .name = "ispb_aclk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4,
+};
+
+static struct fh_clk vpu_clk = {
+ .name = "vpu_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80000000,
+};
+
+static struct fh_clk pix_clk = {
+ .name = "pix_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk jpeg_clk = {
+ .name = "jpeg_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x40000000,
+ .def_rate = CONFIG_JPEG_CLK_RATE,
+};
+
+static struct fh_clk bgm_clk = {
+ .name = "bgm_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x40000,
+};
+
+static struct fh_clk jpeg_adapt_clk = {
+ .name = "jpeg_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&jpeg_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2,
+};
+static struct fh_clk spi0_clk = {
+ .name = "spi0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100,
+};
+static struct fh_clk sdc0_clk = {
+ .name = "sdc0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x4,
+};
+static struct fh_clk spi2_clk = {
+ .name = "spi2_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100000,
+};
+static struct fh_clk spi1_clk = {
+ .name = "spi1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x200,
+};
+static struct fh_clk sdc1_clk = {
+ .name = "sdc1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x2,
+};
+
+static struct fh_clk veu_clk = {
+ .name = "veu_clk",
+ .flag = CLOCK_MULTI_PARENT,
+ .parent = {&pll_sys_pclk, &pll_sys_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x4,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0x7000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000000,
+ .def_rate = CONFIG_VEU_CLK_RATE,
+
+};
+
+static struct fh_clk veu_adapt_clk = {
+ .name = "veu_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&veu_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000000,
+
+};
+
+static struct fh_clk cis_clk_out = {
+ .name = "cis_clk_out",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800000,
+};
+
+static struct fh_clk eth_clk = {
+ .name = "eth_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x12000000,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x20000,
+};
+static struct fh_clk i2c0_clk = {
+ .name = "i2c0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400,
+};
+
+static struct fh_clk i2c1_clk = {
+ .name = "i2c1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800,
+};
+
+static struct fh_clk i2c2_clk = {
+ .name = "i2c2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x00003f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x00000008,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20000000,
+};
+
+static struct fh_clk pwm_clk = {
+ .name = "pwm_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x80,
+ .def_rate = 50000000,
+};
+
+static struct fh_clk uart0_clk = {
+ .name = "uart0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x4000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk uart1_clk = {
+ .name = "uart1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000,
+ .def_rate = 16666666,
+};
+static struct fh_clk uart2_clk = {
+ .name = "uart2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = 0,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x7f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk efuse_clk = {
+ .name = "efuse_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800000,
+};
+
+static struct fh_clk pts_clk = {
+ .name = "pts_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = CLOCK_NORESET,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0x1ff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL2,
+ .rst_reg_mask = 0x1,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk tmr0_clk = {
+ .name = "tmr0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x40000,
+};
+
+static struct fh_clk sadc_clk = {
+ .name = "sadc_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x7f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10000,
+};
+
+static struct fh_clk ac_clk = {
+ .name = "ac_clk",
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1000,
+};
+
+static struct fh_clk i2s_clk = {
+ .name = "i2s_clk",
+ .parent = {&ac_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000,
+};
+
+static struct fh_clk wdt_clk = {
+ .name = "wdt_clk",
+ .flag = 0,
+ .parent = {&ahb_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff00,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_APB_CTRL,
+ .rst_reg_mask = 0x100000,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk gpio0_db_clk = {
+ .name = "gpio0_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio1_db_clk = {
+ .name = "gpio1_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff0000,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x80000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20,
+};
+
+
+static struct fh_clk mipi_dphy_clk = {
+ .name = "mipi_dphy_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100000,
+};
+static struct fh_clk mipi_wrap_gate = {
+ .name = "mipi_wrap_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk rtc_hclk_gate = {
+ .name = "rtc_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk emac_hclk_gate = {
+ .name = "emac_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk usb_clk = {
+ .name = "usb_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk aes_hclk_gate = {
+ .name = "aes_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80,
+};
+static struct fh_clk ephy_clk_gate = {
+ .name = "ephy_clk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1,
+};
+static struct fh_clk sdc0_clk8x_gate = {
+ .name = "sdc0_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4,
+};
+static struct fh_clk sdc1_clk8x_gate = {
+ .name = "sdc1_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8,
+};
+static struct fh_clk mipic_pclk_gate = {
+ .name = "mipic_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio0_pclk_gate = {
+ .name = "gpio0_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x4000,
+};
+static struct fh_clk gpio1_pclk_gate = {
+ .name = "gpio1_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x40000000,
+};
+static struct fh_clk isp_hclk_gate = {
+ .name = "isp_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk veu_hclk_gate = {
+ .name = "veu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk bgm_hclk_gate = {
+ .name = "bgm_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x4000000,
+};
+static struct fh_clk adapt_hclk_gate = {
+ .name = "adapt_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x8000000,
+};
+static struct fh_clk jpg_hclk_gate = {
+ .name = "jpg_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk jpg_adapt_gate = {
+ .name = "jpg_adapt_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk vpu_hclk_gate = {
+ .name = "vpu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x40000000,
+};
+
+static struct fh_clk sdc0_clk_sample = {
+ .name = "sdc0_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf0000,
+};
+
+static struct fh_clk sdc0_clk_drv = {
+ .name = "sdc0_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00000,
+};
+
+static struct fh_clk sdc1_clk_sample = {
+ .name = "sdc1_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00,
+};
+
+static struct fh_clk sdc1_clk_drv = {
+ .name = "sdc1_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf000,
+};
+
+struct fh_clk *fh_clks[] = {
+ &osc_clk,
+ &pll_ddr_rclk,
+ &pll_cpu_pclk,
+ &pll_cpu_rclk,
+ &pll_sys_pclk,
+ &pll_sys_rclk,
+ &arm_clk,
+ &arc_clk,
+ &ahb_clk,
+ &ddr_clk,
+ &isp_aclk,
+ &ispb_aclk,
+ &jpeg_clk,
+ &jpeg_adapt_clk,
+ &vpu_clk,
+ &veu_clk,
+ &veu_adapt_clk,
+ &bgm_clk,
+ &mipi_dphy_clk,
+ &pllsysp_div12_clk,
+ &cis_clk_out,
+ &pix_clk,
+ &pts_clk,
+ &spi0_clk,
+ &spi1_clk,
+ &spi2_clk,
+ &sdc0_clk,
+ &sdc1_clk,
+ &uart0_clk,
+ &uart1_clk,
+ &uart2_clk,
+ &i2c0_clk,
+ &i2c1_clk,
+ &i2c2_clk,
+ &pwm_clk,
+ &wdt_clk,
+ &tmr0_clk,
+ &ac_clk,
+ &i2s_clk,
+ &sadc_clk,
+ &eth_clk,
+ &efuse_clk,
+ &gpio0_db_clk,
+ &gpio1_db_clk,
+ &mipi_wrap_gate,
+ &rtc_hclk_gate,
+ &emac_hclk_gate,
+ &usb_clk,
+ &aes_hclk_gate,
+ &ephy_clk_gate,
+ &sdc0_clk8x_gate,
+ &sdc1_clk8x_gate,
+ &gpio0_pclk_gate,
+ &gpio1_pclk_gate,
+ &mipic_pclk_gate,
+ &sdc0_clk_sample,
+ &sdc0_clk_drv,
+ &sdc1_clk_sample,
+ &sdc1_clk_drv,
+ &isp_hclk_gate,
+ &veu_hclk_gate,
+ &bgm_hclk_gate,
+ &adapt_hclk_gate,
+ &jpg_hclk_gate,
+ &jpg_adapt_gate,
+ &vpu_hclk_gate,
+ NULL,
+};
+EXPORT_SYMBOL(fh_clks);
diff --git a/arch/arm/mach-fh/fh8858v200/chip.h b/arch/arm/mach-fh/fh8858v200/chip.h
new file mode 100644
index 00000000..e552f718
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v200/chip.h
@@ -0,0 +1,422 @@
+#ifndef __ASM_ARCH_HL_H
+#define __ASM_ARCH_HL_H
+
+#include <linux/init.h>
+
+#define SRAM_GRANULARITY 32
+#define SRAM_SIZE (SZ_128K+SZ_8K)
+
+
+#define RAM_BASE (0x10000000)
+#define DDR_BASE (0xA0000000)
+
+
+#define PMU_REG_BASE (0xF0000000)
+#define TIMER_REG_BASE (0xF0C00000)
+#define GPIO0_REG_BASE (0xF0300000)
+#define GPIO1_REG_BASE (0xF4000000)
+#define UART0_REG_BASE (0xF0700000)
+#define UART1_REG_BASE (0xF0800000)
+#define SPI0_REG_BASE (0xF0500000)
+#define SPI1_REG_BASE (0xF0600000)
+#define SPI2_REG_BASE (0xF0640000)
+#define INTC_REG_BASE (0xE0200000)
+#define GMAC_REG_BASE (0xE0600000)
+#define USBC_REG_BASE (0xE0700000)
+#define DMAC_REG_BASE (0xE0300000)
+#define I2C1_REG_BASE (0xF0B00000)
+#define I2C0_REG_BASE (0xF0200000)
+#define I2C2_REG_BASE (0xF0100000)
+#define SDC0_REG_BASE (0xE2000000)
+#define SDC1_REG_BASE (0xE2200000)
+#define WDT_REG_BASE (0xF0D00000)
+#define PWM_REG_BASE (0xF0400000)
+#define I2S_REG_BASE (0xF0900000)
+#define ACW_REG_BASE (0xF0A00000)
+#define UART2_REG_BASE (0xF1300000)
+#define SADC_REG_BASE (0xF1200000)
+#define EFUSE_REG_BASE (0xF1600000)
+#define AES_REG_BASE (0xE8200000)
+#define RTC_REG_BASE (0xF1500000)
+#define DDRC_REG_BASE (0xED000000)
+#define CONSOLE_REG_BASE UART0_REG_BASE
+#define FH_UART_NUMBER 3
+
+#define FH_PMU_REG_SIZE 0x2110
+#define REG_PMU_CHIP_ID (0x0000)
+#define REG_PMU_IP_VER (0x0004)
+#define REG_PMU_FW_VER (0x0008)
+#define REG_PMU_CLK_SEL (0x000c)
+/*for HL REG_PMU_SYS_CTRL and CLK_SEL use one register */
+#define REG_PMU_SYS_CTRL (0x000c)
+#define REG_PMU_PLL0 (0x0010)
+#define REG_PMU_PLL1 (0x0014)
+#define REG_PMU_PLL0_CTRL (0x0018)
+#define REG_PMU_CLK_GATE (0x001c)
+#define REG_PMU_CLK_GATE1 (0x0020)
+#define REG_PMU_CLK_DIV0 (0x0024)
+#define REG_PMU_CLK_DIV1 (0x0028)
+#define REG_PMU_CLK_DIV2 (0x002c)
+#define REG_PMU_CLK_DIV3 (0x0030)
+#define REG_PMU_CLK_DIV4 (0x0034)
+#define REG_PMU_CLK_DIV5 (0x0038)
+#define REG_PMU_CLK_DIV6 (0x003c)
+#define REG_PMU_SWRST_MAIN_CTRL (0x0040)
+#define REG_PMU_SWRST_MAIN_CTRL2 (0x0044)
+#define REG_PMU_SWRST_AHB_CTRL (0x0048)
+#define REG_PMU_SWRST_APB_CTRL (0x004c)
+#define REG_PMU_SPC_IO_STATUS (0x0054)
+#define REG_PMU_SPC_FUN (0x0058)
+#define REG_PMU_CLK_DIV7 (0x005c)
+#define REG_PMU_CLK_DIV8 (0x0060)
+#define REG_PMU_PLL2 (0x0064)
+#define REG_PMU_PLL2_CTRL (0x0068)
+#define REG_PMU_PLL1_CTRL (0x006c)
+#define REG_PAD_PWR_SEL (0x0074)
+#define REG_PMU_SWRSTN_NSR (0x0078)
+#define REG_PMU_SWRSTN_NSR1 (0x007c)
+#define REG_PMU_ETHPHY_REG0 (0x2108)
+
+
+#define REG_PMU_PAD_BOOT_MODE_CFG (0x0080)
+#define REG_PMU_PAD_BOOT_SEL1_CFG (0x0084)
+#define REG_PMU_PAD_BOOT_SEL0_CFG (0x0088)
+#define REG_PMU_PAD_UART0_TX_CFG (0x008c)
+#define REG_PMU_PAD_UART0_RX_CFG (0x0090)
+#define REG_PMU_PAD_I2C0_SCL_CFG (0x0094)
+#define REG_PMU_PAD_I2C0_SDA_CFG (0x0098)
+#define REG_PMU_PAD_SENSOR_CLK_CFG (0x009c)
+#define REG_PMU_PAD_SENSOR_RSTN_CFG (0x00a0)
+#define REG_PMU_PAD_UART1_TX_CFG (0x00a4)
+#define REG_PMU_PAD_UART1_RX_CFG (0x00a8)
+#define REG_PMU_PAD_I2C1_SCL_CFG (0x00ac)
+#define REG_PMU_PAD_I2C1_SDA_CFG (0x00b0)
+#define REG_PMU_PAD_UART2_TX_CFG (0x00b4)
+#define REG_PMU_PAD_UART2_RX_CFG (0x00b8)
+#define REG_PMU_PAD_USB_PWREN_CFG (0x00bc)
+#define REG_PMU_PAD_PWM0_CFG (0x00c0)
+#define REG_PMU_PAD_PWM1_CFG (0x00c4)
+#define REG_PMU_PAD_PWM2_CFG (0x00c8)
+#define REG_PMU_PAD_PWM3_CFG (0x00cc)
+#define REG_PMU_PAD_MAC_RMII_CLK_CFG (0x00d0)
+#define REG_PMU_PAD_MAC_REF_CLK_CFG (0x00d4)
+#define REG_PMU_PAD_MAC_TXD0_CFG (0x00d8)
+#define REG_PMU_PAD_MAC_TXD1_CFG (0x00dc)
+#define REG_PMU_PAD_MAC_TXEN_CFG (0x00e0)
+#define REG_PMU_PAD_MAC_RXD0_CFG (0x00e4)
+#define REG_PMU_PAD_MAC_RXD1_CFG (0x00e8)
+#define REG_PMU_PAD_MAC_RXDV_CFG (0x00ec)
+#define REG_PMU_PAD_MAC_MDC_CFG (0x00f0)
+#define REG_PMU_PAD_MAC_MDIO_CFG (0x00f4)
+#define REG_PMU_PAD_SD1_CLK_CFG (0x00f8)
+#define REG_PMU_PAD_SD1_CD_CFG (0x00fc)
+#define REG_PMU_PAD_SD1_CMD_RSP_CFG (0x0100)
+#define REG_PMU_PAD_SD1_DATA_0_CFG (0x0104)
+#define REG_PMU_PAD_SD1_DATA_1_CFG (0x0108)
+#define REG_PMU_PAD_SD1_DATA_2_CFG (0x010c)
+#define REG_PMU_PAD_SD1_DATA_3_CFG (0x0110)
+#define REG_PMU_PAD_GPIO_0_CFG (0x0114)
+#define REG_PMU_PAD_GPIO_1_CFG (0x0118)
+#define REG_PMU_PAD_GPIO_2_CFG (0x011c)
+#define REG_PMU_PAD_GPIO_3_CFG (0x0120)
+#define REG_PMU_PAD_GPIO_4_CFG (0x0124)
+#define REG_PMU_PAD_SSI0_CLK_CFG (0x0128)
+#define REG_PMU_PAD_SSI0_CSN_0_CFG (0x012c)
+#define REG_PMU_PAD_SSI0_TXD_CFG (0x0130)
+#define REG_PMU_PAD_SSI0_RXD_CFG (0x0134)
+#define REG_PMU_PAD_SSI0_D2_CFG (0x0138)
+#define REG_PMU_PAD_SSI0_D3_CFG (0x013c)
+#define REG_PMU_PAD_SSI1_CLK_CFG (0x0140)
+#define REG_PMU_PAD_SSI1_CSN_0_CFG (0x0144)
+#define REG_PMU_PAD_SSI1_TXD_CFG (0x0148)
+#define REG_PMU_PAD_SSI1_RXD_CFG (0x014c)
+#define REG_PMU_PAD_SD0_CD_CFG (0x0150)
+#define REG_PMU_PAD_SD0_CLK_CFG (0x0154)
+#define REG_PMU_PAD_SD0_CMD_RSP_CFG (0x0158)
+#define REG_PMU_PAD_SD0_DATA_0_CFG (0x015c)
+#define REG_PMU_PAD_SD0_DATA_1_CFG (0x0160)
+#define REG_PMU_PAD_SD0_DATA_2_CFG (0x0164)
+#define REG_PMU_PAD_SD0_DATA_3_CFG (0x0168)
+#define REG_PMU_PAD_SADC_XAIN0_CFG (0x016c)
+#define REG_PMU_PAD_SADC_XAIN1_CFG (0x0170)
+#define REG_PMU_PAD_SADC_XAIN2_CFG (0x0174)
+#define REG_PMU_PAD_SADC_XAIN3_CFG (0x0178)
+#define REG_PMU_PAD_GPIO_28_CFG (0x017c)
+#define REG_PMU_PAD_GPIO_29_CFG (0x0180)
+
+#define REG_PMU_ARM_INT_0 (0x01e0)
+#define REG_PMU_ARM_INT_1 (0x01e4)
+#define REG_PMU_ARM_INT_2 (0x01e8)
+#define REG_PMU_A625_INT_0 (0x01ec)
+#define REG_PMU_A625_INT_1 (0x01f0)
+#define REG_PMU_A625_INT_2 (0x01f4)
+#define REG_PMU_DMA (0x01f8)
+#define REG_PMU_WDT_CTRL (0x01fc)
+#define REG_PMU_DBG_STAT0 (0x0200)
+#define REG_PMU_DBG_STAT1 (0x0204)
+#define REG_PMU_DBG_STAT2 (0x0208)
+#define REG_PMU_DBG_STAT3 (0x020c)
+#define REG_PMU_USB_SYS (0x0210)
+#define REG_PMU_USB_CFG (0x0214)
+#define REG_PMU_USB_TUNE (0x0218)
+#define REG_PMU_USB_SYS1 (0x0228)
+#define REG_PMU_PTSLO (0x022c)
+#define REG_PMU_PTSHI (0x0230)
+#define REG_PMU_USER0 (0x0234)
+#define REG_PMU_BOOT_MODE (0x0330)
+#define REG_PMU_DDR_SIZE (0x0334)
+#define REG_PMU_RESERVED2 (0x0338)
+#define REG_PMU_CHIP_INFO (0x033c)
+#define REG_PMU_EPHY_PARAM (0x0340)
+#define REG_PMU_RTC_PARAM (0x0344)
+#define REG_PMU_SD1_FUNC_SEL (0x03a0)
+#define REG_PMU_PRDCID_CTRL0 (0x0500)
+#define REG_PMU_A625BOOT0 (0x2000)
+#define REG_PMU_A625BOOT1 (0x2004)
+#define REG_PMU_A625BOOT2 (0x2008)
+#define REG_PMU_A625BOOT3 (0x200c)
+#define REG_PMU_A625_START_CTRL (0x2010)
+#define REG_PMU_ARC_INTC_MASK (0x2014)
+
+#define FH_GMAC_AHB_RESET (1<<17)
+#define FH_GMAC_SPEED_100M (1<<24)
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+#define PMU_RXDV_GPIO_SWITCH (REG_PMU_PAD_MAC_RXDV_CFG)
+#define PMU_RXDV_GPIO_MASK (0x0f000000)
+#define PMU_RXDV_GPIO_VAL (0x01000000)
+
+#define PMU_DWI2S_CLK_SEL_REG (REG_PMU_CLK_SEL)
+#define PMU_DWI2S_CLK_SEL_SHIFT (1)
+#define PMU_DWI2S_CLK_DIV_REG (REG_PMU_CLK_DIV6)
+#define PMU_DWI2S_CLK_DIV_SHIFT (0)
+
+/*ATTENTION: written by ARC */
+#define PMU_ARM_INT_MASK (0x01ec)
+#define PMU_ARM_INT_RAWSTAT (0x01f0)
+#define PMU_ARM_INT_STAT (0x01f4)
+
+#define PMU_A625_INT_MASK (0x01e0)
+#define PMU_A625_INT_RAWSTAT (0x01e4)
+#define PMU_A625_INT_STAT (0x01e8)
+
+#define PMU_IRQ 0
+#define DDRC_IRQ 1
+#define WDT_IRQ 2
+#define TMR0_IRQ 3
+#define VEU_IRQ 4
+#define PERF_IRQ 5
+#define VPU_IRQ 9
+#define I2C0_IRQ 11
+#define I2C1_IRQ 12
+#define JPEG_IRQ 13
+#define BGM_IRQ 14
+#define VEU_LOOP_IRQ 15
+#define AES_IRQ 16
+#define MIPIC_IRQ 17
+#define MIPI_WRAP_IRQ 18
+#define ACW_IRQ 19
+#define SADC_IRQ 20
+#define SPI1_IRQ 21
+#define JPEG_LOOP_IRQ 22
+#define DMAC0_IRQ 23
+#define DMAC1_IRQ 24
+#define I2S0_IRQ 25
+#define GPIO0_IRQ 26
+#define SPI0_IRQ 28
+#define ARC_SW_IRQ 29
+#define UART0_IRQ 30
+#define UART1_IRQ 31
+#define ARM_SW_IRQ 32
+#define RTC_IRQ 33
+#define PWM_IRQ 36
+#define SPI2_IRQ 38
+#define USBC_IRQ 39
+#define GPIO1_IRQ 40
+#define UART2_IRQ 41
+#define SDC0_IRQ 42
+#define SDC1_IRQ 43
+#define GMAC_IRQ 44
+#define EPHY_IRQ 45
+#define I2C2_IRQ 46
+#define RTC_ALM_IRQ 47
+#define RTC_CORE_IRQ 48
+/* because chips with some same function in different */
+/* pmu register, use wrap marco to make code to be same */
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+
+#define MEM_START_PHY_ADDR DDR_BASE
+#define MEM_SIZE 0x8000000
+
+
+#define NR_INTERNAL_IRQS (64)
+#define NR_EXTERNAL_IRQS (64)
+/*#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS)*/
+
+/* SWRST_MAIN_CTRL */
+#define CPU_RSTN_BIT (0)
+#define UTMI_RSTN_BIT (1)
+#define DDRPHY_RSTN_BIT (2)
+#define DDRC_RSTN_BIT (3)
+#define GPIO0_DB_RSTN_BIT (4)
+#define GPIO1_DB_RSTN_BIT (5)
+#define PIXEL_RSTN_BIT (6)
+#define PWM_RSTN_BIT (7)
+#define SPI0_RSTN_BIT (8)
+#define SPI1_RSTN_BIT (9)
+#define I2C0_RSTN_BIT (10)
+#define I2C1_RSTN_BIT (11)
+#define ACODEC_RSTN_BIT (12)
+#define I2S_RSTN_BIT (13)
+#define UART0_RSTN_BIT (14)
+#define UART1_RSTN_BIT (15)
+#define SADC_RSTN_BIT (16)
+#define ADAPT_RSTN_BIT (17)
+#define TMR_RSTN_BIT (18)
+#define UART2_RSTN_BIT (19)
+#define SPI2_RSTN_BIT (20)
+#define JPG_ADAPT_RSTN_BIT (21)
+#define ARC_RSTN_BIT (22)
+#define EFUSE_RSTN_BIT (23)
+#define JPG_RSTN_BIT (24)
+#define VEU_RSTN_BIT (25)
+#define VPU_RSTN_BIT (26)
+#define ISP_RSTN_BIT (27)
+#define BGM_RSTN_BIT (28)
+#define I2C2_RSTN_BIT (29)
+#define EPHY_RSTN_BIT (30)
+#define SYS_RSTN_BIT (31)
+
+/* SWRST_AHB_CTRL */
+#define EMC_HRSTN_BIT (0)
+#define SDC1_HRSTN_BIT (1)
+#define SDC0_HRSTN_BIT (2)
+#define AES_HRSTN_BIT (3)
+#define DMAC0_HRSTN_BIT (4)
+#define INTC_HRSTN_BIT (5)
+#define JPEG_ADAPT_HRSTN_BIT (7)
+#define JPEG_HRSTN_BIT (8)
+#define VCU_HRSTN_BIT (9)
+#define VPU_HRSTN_BIT (10)
+#define ISP_HRSTN_BIT (11)
+#define USB_HRSTN_BIT (12)
+#define HRSTN_BIT (13)
+#define EMAC_HRSTN_BIT (17)
+#define DDRC_HRSTN_BIT (19)
+#define DMAC1_HRSTN_BIT (20)
+#define BGM_HRSTN_BIT (22)
+#define ADAPT_HRSTN_BIT (23)
+
+
+/* SWRST_APB_CTRL */
+#define ACODEC_PRSTN_BIT (0)
+#define I2S_PRSTN_BIT (1)
+#define UART1_PRSTN_BIT (2)
+#define UART0_PRSTN_BIT (3)
+#define SPI0_PRSTN_BIT (4)
+#define SPI1_PRSTN_BIT (5)
+#define GPIO0_PRSTN_BIT (6)
+#define UART2_PRSTN_BIT (7)
+#define I2C2_PRSTN_BIT (8)
+#define I2C0_PRSTN_BIT (9)
+#define I2C1_PRSTN_BIT (10)
+#define TMR_PRSTN_BIT (11)
+#define PWM_PRSTN_BIT (12)
+#define MIPIW_PRSTN_BIT (13)
+#define MIPIC_PRSTN_BIT (14)
+#define RTC_PRSTN_BIT (15)
+#define SADC_PRSTN_BIT (16)
+#define EFUSE_PRSTN_BIT (17)
+#define SPI2_PRSTN_BIT (18)
+#define WDT_PRSTN_BIT (19)
+#define GPIO1_PRSTN_BIT (20)
+
+/* timer clk fpga 1M,soc 50M*/
+#ifdef CONFIG_FPGA
+#define TIMER_CLK (1000000)
+#else
+#define TIMER_CLK (50000000)
+#endif
+
+#define UART1_TX_HW_HANDSHAKE (9)
+#define UART1_RX_HW_HANDSHAKE (8)
+#define UART2_TX_HW_HANDSHAKE (13)
+#define UART2_RX_HW_HANDSHAKE (12)
+#define UART1_DMA_TX_CHAN (4)
+#define UART1_DMA_RX_CHAN (5)
+#define UART2_DMA_TX_CHAN (4)
+#define UART2_DMA_RX_CHAN (5)
+
+/*sdio*/
+#define SIMPLE_0 (0)
+#define SIMPLE_22 (1)
+#define SIMPLE_45 (2)
+#define SIMPLE_67 (3)
+#define SIMPLE_90 (4)
+#define SIMPLE_112 (5)
+#define SIMPLE_135 (6)
+#define SIMPLE_157 (7)
+#define SIMPLE_180 (8)
+#define SIMPLE_202 (9)
+#define SIMPLE_225 (10)
+#define SIMPLE_247 (11)
+#define SIMPLE_270 (12)
+#define SIMPLE_292 (13)
+#define SIMPLE_315 (14)
+#define SIMPLE_337 (15)
+
+
+
+#define SDIO0_RST_BIT (~UL(1<<2))
+#define SDIO0_CLK_RATE (50000000)
+#define SDIO0_CLK_DRV_SHIFT (20)
+#define SDIO0_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO0_CLK_SAM_SHIFT (16)
+#define SDIO0_CLK_SAM_DEGREE (SIMPLE_0)
+
+
+#define SDIO1_RST_BIT (~UL(1<<1))
+#define SDIO1_CLK_RATE (50000000)
+#define SDIO1_CLK_DRV_SHIFT (12)
+#define SDIO1_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO1_CLK_SAM_SHIFT (8)
+#define SDIO1_CLK_SAM_DEGREE (SIMPLE_0)
+
+#define SDC0_HRSTN (0x1<<2)
+#define SDC1_HRSTN (0x1<<1)
+#define SDC2_HRSTN (0)
+
+
+/*usb*/
+#define IRQ_UHOST USBC_IRQ
+#define FH_PA_OTG USBC_REG_BASE
+#define IRQ_OTG IRQ_UHOST
+#define FH_SZ_USBHOST SZ_1M
+#define FH_SZ_OTG SZ_1M
+
+#define USB_UTMI_RST_BIT (0x1<<1)
+#define USB_PHY_RST_BIT (0x11)
+#define USB_SLEEP_MODE_BIT (0x1<<24)
+#define USB_IDDQ_PWR_BIT (0x1<<10)
+
+
+/* Specific Uart Number */
+#define FH_UART_NUMBER 3
+#define CLK_SCAN_BIT_POS (28)
+#define INSIDE_PHY_ENABLE_BIT_POS (24)
+#define MAC_REF_CLK_DIV_MASK (0x0f)
+#define MAC_REF_CLK_DIV_BIT_POS (24)
+#define MAC_PAD_RMII_CLK_MASK (0x0f)
+#define MAC_PAD_RMII_CLK_BIT_POS (24)
+#define MAC_PAD_MAC_REF_CLK_BIT_POS (28)
+#define ETH_REF_CLK_OUT_GATE_BIT_POS (25)
+#define ETH_RMII_CLK_OUT_GATE_BIT_POS (28)
+#define IN_OR_OUT_PHY_SEL_BIT_POS (26)
+#define INSIDE_CLK_GATE_BIT_POS (0)
+#define INSIDE_PHY_SHUTDOWN_BIT_POS (31)
+#define INSIDE_PHY_RST_BIT_POS (30)
+#define INSIDE_PHY_TRAINING_BIT_POS (27)
+#define INSIDE_PHY_TRAINING_MASK (0x0f)
+
+#define TRAINING_EFUSE_ACTIVE_BIT_POS 4
+
+#endif /* __ASM_ARCH_HL_H */
diff --git a/arch/arm/mach-fh/fh8858v200/iopad.h b/arch/arm/mach-fh/fh8858v200/iopad.h
new file mode 100644
index 00000000..be10c032
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v200/iopad.h
@@ -0,0 +1,729 @@
+#include <mach/pinctrl.h>
+#include <mach/pinctrl_osdep.h>
+#include <mach/board_config.h>
+
+/* PINCTRL_FUNC */
+PINCTRL_FUNC(GPIO30, 0, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO31, 1, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 1, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO32, 2, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 2, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 2, FUNC2, PUPD_UP, 0);
+PINCTRL_FUNC(UART0_TX, 3, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO33, 3, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART0_RX, 4, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO34, 4, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C0_SCL, 5, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO35, 5, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(I2C0_SDA, 6, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO36, 6, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(SENSOR_CLK, 7, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO12, 7, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO13, 8, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 9, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO39, 9, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 9, FUNC3, PUPD_NONE, 3);
+PINCTRL_FUNC(TEST_O_INT_RMII_CLK, 9, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 10, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO40, 10, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 10, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_0, 10, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 11, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO37, 11, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 11, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 11, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 11, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_1, 11, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 12, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO38, 12, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 12, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 12, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 12, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXEN, 12, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 13, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO41, 13, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM4, 13, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 13, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 13, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_0, 13, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 14, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO42, 14, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM5, 14, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 14, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 14, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_1, 14, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 15, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO47, 15, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 15, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_CRSDV, 15, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM0, 16, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO43, 16, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SCL, 16, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 16, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_0, 16, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM1, 17, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO44, 17, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SDA, 17, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 17, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_1, 17, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 18, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO45, 18, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 19, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO46, 19, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RMII_CLK, 20, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO48, 20, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 20, FUNC2, PUPD_NONE, 3);
+PINCTRL_FUNC(PWM2, 20, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_REF_CLK, 21, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(MAC_TXD_0, 22, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO49, 22, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 22, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM3, 22, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXD_1, 23, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO50, 23, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 23, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM4, 23, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXEN, 24, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO51, 24, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 24, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM5, 24, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_0, 25, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO52, 25, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 25, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM6, 25, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_1, 26, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO53, 26, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 26, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM7, 26, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXDV, 27, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO54, 27, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 27, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM8, 27, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 28, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO55, 28, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 28, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 29, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO56, 29, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 30, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO57, 30, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 30, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 31, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO58, 31, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 31, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO59, 32, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 32, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 33, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO60, 33, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 33, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 34, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO61, 34, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 34, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 35, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO62, 35, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 35, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 36, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO63, 36, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TRSTN, 37, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO0, 37, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DO, 37, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DO, 37, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CLK, 37, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CLK, 37, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADDAT, 37, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM6, 37, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDC, 37, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDO, 38, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO1, 38, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DI, 38, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DI, 38, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CSN_0, 38, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DADAT, 38, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM7, 38, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_I, 38, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDI, 39, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO2, 39, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_CLK, 39, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_CLK, 39, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_TXD, 39, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_TXD, 39, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADBCLK, 39, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM8, 39, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_O, 39, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TCK, 40, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO3, 40, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_WS, 40, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_WS, 40, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_RXD, 40, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_RXD, 40, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADLRC, 40, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 40, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDIO_I, 40, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TMS, 41, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO4, 41, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_MCLK, 41, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 41, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 41, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDC, 41, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI0_CLK, 42, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO5, 42, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CLK, 42, FUNC4, PUPD_NONE, 3);
+PINCTRL_FUNC(SSI0_CSN_0, 43, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO6, 43, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CMD_RSP, 43, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_TXD, 44, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO7, 44, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_0, 44, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_RXD, 45, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO8, 45, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_1, 45, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D2, 46, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO9, 46, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_TX, 46, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SCL, 46, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_2, 46, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D3, 47, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO10, 47, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_RX, 47, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SDA, 47, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_3, 47, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 48, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO11, 48, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CLK, 48, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 49, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CSN_0, 49, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 50, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO15, 50, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_TXD, 50, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 51, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO16, 51, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_RXD, 51, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CD, 52, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO17, 52, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARC_JTAG_TRSTN, 52, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(PAE_JTAG_TRSTN, 52, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD0_CLK, 53, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO18, 53, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 53, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDO, 53, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDO, 53, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CMD_RSP, 54, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO19, 54, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 54, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDI, 54, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDI, 54, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_0, 55, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO20, 55, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 55, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TCK, 55, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TCK, 55, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_1, 56, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO21, 56, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 56, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TMS, 56, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TMS, 56, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_2, 57, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO22, 57, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_TX, 57, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SCL, 57, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DABCLK, 57, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_3, 58, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO23, 58, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 58, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_RX, 58, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SDA, 58, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DALRC, 58, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SADC_XAIN0, 59, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO26, 59, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN1, 60, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO27, 60, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN2, 61, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO24, 61, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN3, 62, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO25, 62, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO28, 63, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 63, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM10, 63, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_DBG_CLK, 63, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 63, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXEN, 63, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 63, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO29, 64, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 64, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM11, 64, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(RTC_CLK, 64, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 64, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_OE, 64, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 64, FUNC7, PUPD_NONE, 0);
+
+
+/* PINCTRL_MUX */
+
+PINCTRL_MUX(AC_I2S_CLK, 0, &PAD39_AC_I2S_CLK);
+PINCTRL_MUX(AC_I2S_DI, 0, &PAD38_AC_I2S_DI);
+PINCTRL_MUX(AC_I2S_DO, 0, &PAD37_AC_I2S_DO);
+PINCTRL_MUX(AC_I2S_WS, 0, &PAD40_AC_I2S_WS);
+PINCTRL_MUX(AC_MCLK, 0, &PAD41_AC_MCLK);
+
+PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD55_ARC_JTAG_TCK);
+PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD54_ARC_JTAG_TDI);
+PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD53_ARC_JTAG_TDO);
+PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD56_ARC_JTAG_TMS);
+PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD52_ARC_JTAG_TRSTN);
+
+PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD40_ARM_JTAG_TCK);
+PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD39_ARM_JTAG_TDI);
+PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD38_ARM_JTAG_TDO);
+PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD41_ARM_JTAG_TMS);
+PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD37_ARM_JTAG_TRSTN);
+
+PINCTRL_MUX(DW_I2S_CLK, 0, &PAD39_DW_I2S_CLK);
+PINCTRL_MUX(DW_I2S_DI, 0, &PAD38_DW_I2S_DI);
+PINCTRL_MUX(DW_I2S_DO, 0, &PAD37_DW_I2S_DO);
+PINCTRL_MUX(DW_I2S_WS, 0, &PAD40_DW_I2S_WS);
+
+PINCTRL_MUX(ETH_LINK_ACT, 1, &PAD1_ETH_LINK_ACT,
+ &PAD63_ETH_LINK_ACT);
+PINCTRL_MUX(ETH_LINK_SPD, 1, &PAD2_ETH_LINK_SPD,
+ &PAD64_ETH_LINK_SPD);
+PINCTRL_MUX(ETH_LINK_STA, 1, &PAD2_ETH_LINK_STA,
+ &PAD64_ETH_LINK_STA);
+
+PINCTRL_MUX(I2C0_SCL, 0, &PAD5_I2C0_SCL);
+PINCTRL_MUX(I2C0_SDA, 0, &PAD6_I2C0_SDA);
+
+PINCTRL_MUX(I2C1_SCL, 2, &PAD11_I2C1_SCL, &PAD30_I2C1_SCL, &PAD46_I2C1_SCL);
+PINCTRL_MUX(I2C1_SDA, 2, &PAD12_I2C1_SDA, &PAD31_I2C1_SDA, &PAD47_I2C1_SDA);
+
+PINCTRL_MUX(I2C2_SCL, 1, &PAD16_I2C2_SCL, &PAD57_I2C2_SCL);
+PINCTRL_MUX(I2C2_SDA, 1, &PAD17_I2C2_SDA, &PAD58_I2C2_SDA);
+
+PINCTRL_MUX(MAC_MDC, 0, &PAD28_MAC_MDC, &PAD63_MAC_MDC);
+PINCTRL_MUX(MAC_MDIO, 0, &PAD29_MAC_MDIO, &PAD64_MAC_MDIO);
+PINCTRL_MUX(MAC_REF_CLK, 0, &PAD21_MAC_REF_CLK);
+PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD20_MAC_RMII_CLK);
+PINCTRL_MUX(MAC_RXDV, 0, &PAD27_MAC_RXDV);
+PINCTRL_MUX(MAC_RXD_0, 0, &PAD25_MAC_RXD_0);
+PINCTRL_MUX(MAC_RXD_1, 0, &PAD26_MAC_RXD_1);
+PINCTRL_MUX(MAC_TXD_0, 0, &PAD22_MAC_TXD_0);
+PINCTRL_MUX(MAC_TXD_1, 0, &PAD23_MAC_TXD_1);
+PINCTRL_MUX(MAC_TXEN, 0, &PAD24_MAC_TXEN);
+
+PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD55_PAE_JTAG_TCK);
+PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD54_PAE_JTAG_TDI);
+PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD53_PAE_JTAG_TDO);
+PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD56_PAE_JTAG_TMS);
+PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD52_PAE_JTAG_TRSTN);
+
+PINCTRL_MUX(PWM0, 0, &PAD16_PWM0);
+PINCTRL_MUX(PWM1, 0, &PAD17_PWM1);
+PINCTRL_MUX(PWM10, 0, &PAD63_PWM10);
+PINCTRL_MUX(PWM11, 0, &PAD64_PWM11);
+PINCTRL_MUX(PWM2, 0, &PAD11_PWM2, &PAD18_PWM2, &PAD20_PWM2);
+PINCTRL_MUX(PWM3, 0, &PAD12_PWM3, &PAD19_PWM3, &PAD22_PWM3);
+PINCTRL_MUX(PWM4, 0, &PAD13_PWM4, &PAD23_PWM4);
+PINCTRL_MUX(PWM5, 0, &PAD14_PWM5, &PAD24_PWM5);
+PINCTRL_MUX(PWM6, 1, &PAD25_PWM6, &PAD37_PWM6);
+PINCTRL_MUX(PWM7, 1, &PAD26_PWM7, &PAD38_PWM7);
+PINCTRL_MUX(PWM8, 1, &PAD27_PWM8, &PAD39_PWM8);
+PINCTRL_MUX(PWM9, 1, &PAD28_PWM9, &PAD40_PWM9);
+
+PINCTRL_MUX(RTC_CLK, 0, &PAD64_RTC_CLK);
+
+PINCTRL_MUX(SADC_XAIN0, 0, &PAD59_SADC_XAIN0);
+PINCTRL_MUX(SADC_XAIN1, 0, &PAD60_SADC_XAIN1);
+PINCTRL_MUX(SADC_XAIN2, 0, &PAD61_SADC_XAIN2);
+PINCTRL_MUX(SADC_XAIN3, 0, &PAD62_SADC_XAIN3);
+
+PINCTRL_MUX(SD0_CD, 0, &PAD52_SD0_CD);
+PINCTRL_MUX(SD0_CLK, 0, &PAD53_SD0_CLK);
+PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD54_SD0_CMD_RSP);
+PINCTRL_MUX(SD0_DATA_0, 0, &PAD55_SD0_DATA_0);
+PINCTRL_MUX(SD0_DATA_1, 0, &PAD56_SD0_DATA_1);
+PINCTRL_MUX(SD0_DATA_2, 0, &PAD57_SD0_DATA_2);
+PINCTRL_MUX(SD0_DATA_3, 0, &PAD58_SD0_DATA_3);
+
+PINCTRL_MUX(SD1_CD, 2, &PAD10_SD1_CD, &PAD22_SD1_CD, &PAD31_SD1_CD,
+ &PAD41_SD1_CD, &PAD63_SD1_CD);
+PINCTRL_MUX(SD1_CLK, 2, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP, 2, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0, 2, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1, 2, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2, 2, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3, 2, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+PINCTRL_MUX(SENSOR_CLK, 0, &PAD7_SENSOR_CLK);
+
+PINCTRL_MUX(SSI0_CLK, 0, &PAD42_SSI0_CLK);
+PINCTRL_MUX(SSI0_D2, 0, &PAD46_SSI0_D2);
+PINCTRL_MUX(SSI0_D3, 0, &PAD47_SSI0_D3);
+PINCTRL_MUX(SSI0_RXD, 0, &PAD45_SSI0_RXD);
+PINCTRL_MUX(SSI0_TXD, 0, &PAD44_SSI0_TXD);
+
+PINCTRL_MUX(SSI1_CLK, 2, &PAD11_SSI1_CLK, &PAD37_SSI1_CLK, &PAD48_SSI1_CLK,
+ &PAD53_SSI1_CLK);
+PINCTRL_MUX(SSI1_RXD, 2, &PAD14_SSI1_RXD, &PAD40_SSI1_RXD, &PAD51_SSI1_RXD,
+ &PAD55_SSI1_RXD);
+PINCTRL_MUX(SSI1_TXD, 2, &PAD13_SSI1_TXD, &PAD39_SSI1_TXD, &PAD50_SSI1_TXD,
+ &PAD54_SSI1_TXD);
+
+PINCTRL_MUX(SSI2_CLK, 1, &PAD37_SSI2_CLK, &PAD48_SSI2_CLK);
+PINCTRL_MUX(SSI2_CSN_0, 1, &PAD38_SSI2_CSN_0, &PAD49_SSI2_CSN_0);
+PINCTRL_MUX(SSI2_RXD, 1, &PAD40_SSI2_RXD, &PAD51_SSI2_RXD);
+PINCTRL_MUX(SSI2_TXD, 1, &PAD39_SSI2_TXD, &PAD50_SSI2_TXD);
+
+PINCTRL_MUX(UART0_RX, 0, &PAD4_UART0_RX);
+PINCTRL_MUX(UART0_TX, 0, &PAD3_UART0_TX);
+
+PINCTRL_MUX(UART1_RX, 0, &PAD10_UART1_RX, &PAD33_UART1_RX, &PAD47_UART1_RX);
+PINCTRL_MUX(UART1_TX, 0, &PAD9_UART1_TX, &PAD32_UART1_TX, &PAD46_UART1_TX);
+
+PINCTRL_MUX(UART2_RX, 0, &PAD14_UART2_RX, &PAD17_UART2_RX, &PAD35_UART2_RX,
+ &PAD58_UART2_RX);
+PINCTRL_MUX(UART2_TX, 0, &PAD13_UART2_TX, &PAD16_UART2_TX, &PAD34_UART2_TX,
+ &PAD57_UART2_TX);
+
+PINCTRL_MUX(USB_PWREN, 0, &PAD15_USB_PWREN, &PAD41_USB_PWREN);
+
+PINCTRL_MUX(GPIO0, 0, &PAD37_GPIO0);
+PINCTRL_MUX(GPIO1, 0, &PAD38_GPIO1);
+PINCTRL_MUX(GPIO2, 0, &PAD39_GPIO2);
+PINCTRL_MUX(GPIO3, 0, &PAD40_GPIO3);
+PINCTRL_MUX(GPIO4, 0, &PAD41_GPIO4);
+PINCTRL_MUX(GPIO5, 0, &PAD42_GPIO5);
+PINCTRL_MUX(GPIO6, 0, &PAD43_GPIO6);
+PINCTRL_MUX(GPIO7, 0, &PAD44_GPIO7);
+PINCTRL_MUX(GPIO8, 0, &PAD45_GPIO8);
+PINCTRL_MUX(GPIO9, 0, &PAD46_GPIO9);
+PINCTRL_MUX(GPIO10, 0, &PAD47_GPIO10);
+PINCTRL_MUX(GPIO11, 0, &PAD48_GPIO11);
+PINCTRL_MUX(GPIO12, 0, &PAD7_GPIO12);
+PINCTRL_MUX(GPIO13, 0, &PAD8_GPIO13);
+PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14);
+PINCTRL_MUX(GPIO15, 0, &PAD50_GPIO15);
+PINCTRL_MUX(GPIO16, 0, &PAD51_GPIO16);
+PINCTRL_MUX(GPIO17, 0, &PAD52_GPIO17);
+PINCTRL_MUX(GPIO18, 0, &PAD53_GPIO18);
+PINCTRL_MUX(GPIO19, 0, &PAD54_GPIO19);
+PINCTRL_MUX(GPIO20, 0, &PAD55_GPIO20);
+PINCTRL_MUX(GPIO21, 0, &PAD56_GPIO21);
+PINCTRL_MUX(GPIO22, 0, &PAD57_GPIO22);
+PINCTRL_MUX(GPIO23, 0, &PAD58_GPIO23);
+PINCTRL_MUX(GPIO24, 0, &PAD61_GPIO24);
+PINCTRL_MUX(GPIO25, 0, &PAD62_GPIO25);
+PINCTRL_MUX(GPIO26, 0, &PAD59_GPIO26);
+PINCTRL_MUX(GPIO27, 0, &PAD60_GPIO27);
+PINCTRL_MUX(GPIO28, 0, &PAD63_GPIO28);
+PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29);
+PINCTRL_MUX(GPIO30, 0, &PAD0_GPIO30);
+PINCTRL_MUX(GPIO31, 0, &PAD1_GPIO31);
+PINCTRL_MUX(GPIO32, 0, &PAD2_GPIO32);
+PINCTRL_MUX(GPIO33, 0, &PAD3_GPIO33);
+PINCTRL_MUX(GPIO34, 0, &PAD4_GPIO34);
+PINCTRL_MUX(GPIO35, 0, &PAD5_GPIO35);
+PINCTRL_MUX(GPIO36, 0, &PAD6_GPIO36);
+PINCTRL_MUX(GPIO37, 0, &PAD11_GPIO37);
+PINCTRL_MUX(GPIO38, 0, &PAD12_GPIO38);
+PINCTRL_MUX(GPIO39, 0, &PAD9_GPIO39);
+PINCTRL_MUX(GPIO40, 0, &PAD10_GPIO40);
+PINCTRL_MUX(GPIO41, 0, &PAD13_GPIO41);
+PINCTRL_MUX(GPIO42, 0, &PAD14_GPIO42);
+PINCTRL_MUX(GPIO43, 0, &PAD16_GPIO43);
+PINCTRL_MUX(GPIO44, 0, &PAD17_GPIO44);
+PINCTRL_MUX(GPIO45, 0, &PAD18_GPIO45);
+PINCTRL_MUX(GPIO46, 0, &PAD19_GPIO46);
+PINCTRL_MUX(GPIO47, 0, &PAD15_GPIO47);
+PINCTRL_MUX(GPIO48, 0, &PAD20_GPIO48);
+PINCTRL_MUX(GPIO49, 0, &PAD22_GPIO49);
+PINCTRL_MUX(GPIO50, 0, &PAD23_GPIO50);
+PINCTRL_MUX(GPIO51, 0, &PAD24_GPIO51);
+PINCTRL_MUX(GPIO52, 0, &PAD25_GPIO52);
+PINCTRL_MUX(GPIO53, 0, &PAD26_GPIO53);
+PINCTRL_MUX(GPIO54, 0, &PAD27_GPIO54);
+PINCTRL_MUX(GPIO55, 0, &PAD28_GPIO55);
+PINCTRL_MUX(GPIO56, 0, &PAD29_GPIO56);
+PINCTRL_MUX(GPIO57, 0, &PAD30_GPIO57);
+PINCTRL_MUX(GPIO58, 0, &PAD31_GPIO58);
+PINCTRL_MUX(GPIO59, 0, &PAD32_GPIO59);
+PINCTRL_MUX(GPIO60, 0, &PAD33_GPIO60);
+PINCTRL_MUX(GPIO61, 0, &PAD34_GPIO61);
+PINCTRL_MUX(GPIO62, 0, &PAD35_GPIO62);
+PINCTRL_MUX(GPIO63, 0, &PAD36_GPIO63);
+
+PINCTRL_MUX(SD1_CLK_EMMC, 3, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP_EMMC, 3, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0_EMMC, 3, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1_EMMC, 3, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2_EMMC, 3, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3_EMMC, 3, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+/* PINCTRL_DEVICE */
+PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO,
+ &MUX_AC_I2S_WS, &MUX_AC_MCLK);
+PINCTRL_DEVICE(AC_MCLK, 1, &MUX_AC_MCLK);
+PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI,
+ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN);
+PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI,
+ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN);
+PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO,
+ &MUX_DW_I2S_WS);
+PINCTRL_DEVICE(ETH, 2, &MUX_ETH_LINK_ACT, &MUX_ETH_LINK_STA);
+PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA);
+PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA);
+PINCTRL_DEVICE(I2C2, 2, &MUX_I2C2_SCL, &MUX_I2C2_SDA);
+PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI,
+ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN);
+PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0);
+PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1);
+PINCTRL_DEVICE(PWM10, 1, &MUX_PWM10);
+PINCTRL_DEVICE(PWM11, 1, &MUX_PWM11);
+PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2);
+PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3);
+PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4);
+PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5);
+PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6);
+PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7);
+PINCTRL_DEVICE(PWM8, 1, &MUX_PWM8);
+PINCTRL_DEVICE(PWM9, 1, &MUX_PWM9);
+PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK,
+ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1,
+ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN);
+PINCTRL_DEVICE(RTC, 1, &MUX_RTC_CLK);
+PINCTRL_DEVICE(SADC_XAIN0, 1, &MUX_SADC_XAIN0);
+PINCTRL_DEVICE(SADC_XAIN1, 1, &MUX_SADC_XAIN1);
+PINCTRL_DEVICE(SADC_XAIN2, 1, &MUX_SADC_XAIN2);
+PINCTRL_DEVICE(SADC_XAIN3, 1, &MUX_SADC_XAIN3);
+PINCTRL_DEVICE(SD0, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0);
+PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_WIFI, 6, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, &MUX_SD0_DATA_0,
+ &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD1, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_1BIT_NO_WP, 4, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0);
+PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_WIFI, 6, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, &MUX_SD1_DATA_0,
+ &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SENSOR_CLK, 1, &MUX_SENSOR_CLK);
+PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_RXD,
+ &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_D2,
+ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI1, 4, &MUX_GPIO14, &MUX_SSI1_CLK, &MUX_SSI1_RXD,
+ &MUX_SSI1_TXD);
+PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN_0, &MUX_SSI2_RXD,
+ &MUX_SSI2_TXD);
+PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX);
+PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX);
+PINCTRL_DEVICE(UART2, 2, &MUX_UART2_RX, &MUX_UART2_TX);
+PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN);
+PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0);
+PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1);
+PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2);
+PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3);
+PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4);
+PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5);
+PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6);
+PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7);
+PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8);
+PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9);
+PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10);
+PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11);
+PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12);
+PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13);
+PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14);
+PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15);
+PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16);
+PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17);
+PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18);
+PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19);
+PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20);
+PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21);
+PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22);
+PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23);
+PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24);
+PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25);
+PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26);
+PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27);
+PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28);
+PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29);
+PINCTRL_DEVICE(GPIO30, 1, &MUX_GPIO30);
+PINCTRL_DEVICE(GPIO31, 1, &MUX_GPIO31);
+PINCTRL_DEVICE(GPIO32, 1, &MUX_GPIO32);
+PINCTRL_DEVICE(GPIO33, 1, &MUX_GPIO33);
+PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34);
+PINCTRL_DEVICE(GPIO35, 1, &MUX_GPIO35);
+PINCTRL_DEVICE(GPIO36, 1, &MUX_GPIO36);
+PINCTRL_DEVICE(GPIO37, 1, &MUX_GPIO37);
+PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38);
+PINCTRL_DEVICE(GPIO39, 1, &MUX_GPIO39);
+PINCTRL_DEVICE(GPIO40, 1, &MUX_GPIO40);
+PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41);
+PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42);
+PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43);
+PINCTRL_DEVICE(GPIO44, 1, &MUX_GPIO44);
+PINCTRL_DEVICE(GPIO45, 1, &MUX_GPIO45);
+PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46);
+PINCTRL_DEVICE(GPIO47, 1, &MUX_GPIO47);
+PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48);
+PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49);
+PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50);
+PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51);
+PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52);
+PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53);
+PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54);
+PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55);
+PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56);
+PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57);
+PINCTRL_DEVICE(GPIO58, 1, &MUX_GPIO58);
+PINCTRL_DEVICE(GPIO59, 1, &MUX_GPIO59);
+PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60);
+PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61);
+PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62);
+PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63);
+
+PINCTRL_DEVICE(SD1_EMMC, 6, &MUX_SD1_CLK_EMMC, &MUX_SD1_CMD_RSP_EMMC,
+ &MUX_SD1_DATA_0_EMMC, &MUX_SD1_DATA_1_EMMC, &MUX_SD1_DATA_2_EMMC,
+ &MUX_SD1_DATA_3_EMMC);
+
+void fh_pinctrl_init_devicelist(OS_LIST *list)
+{
+ OS_LIST_EMPTY(list);
+
+ /*PINCTRL_ADD_DEVICE*/
+ PINCTRL_ADD_DEVICE(ACI2S);
+ PINCTRL_ADD_DEVICE(AC_MCLK);
+ PINCTRL_ADD_DEVICE(ARCJTAG);
+ PINCTRL_ADD_DEVICE(ARMJTAG);
+ PINCTRL_ADD_DEVICE(DWI2S);
+ PINCTRL_ADD_DEVICE(ETH);
+ PINCTRL_ADD_DEVICE(I2C0);
+ PINCTRL_ADD_DEVICE(I2C1);
+ PINCTRL_ADD_DEVICE(I2C2);
+ PINCTRL_ADD_DEVICE(PAEJTAG);
+ PINCTRL_ADD_DEVICE(PWM0);
+ PINCTRL_ADD_DEVICE(PWM1);
+ PINCTRL_ADD_DEVICE(PWM10);
+ PINCTRL_ADD_DEVICE(PWM11);
+ PINCTRL_ADD_DEVICE(PWM2);
+ PINCTRL_ADD_DEVICE(PWM3);
+ PINCTRL_ADD_DEVICE(PWM4);
+ PINCTRL_ADD_DEVICE(PWM5);
+ PINCTRL_ADD_DEVICE(PWM6);
+ PINCTRL_ADD_DEVICE(PWM7);
+ PINCTRL_ADD_DEVICE(PWM8);
+ PINCTRL_ADD_DEVICE(PWM9);
+ PINCTRL_ADD_DEVICE(RMII);
+ PINCTRL_ADD_DEVICE(RTC);
+ PINCTRL_ADD_DEVICE(SADC_XAIN0);
+ PINCTRL_ADD_DEVICE(SADC_XAIN1);
+ PINCTRL_ADD_DEVICE(SADC_XAIN2);
+ PINCTRL_ADD_DEVICE(SADC_XAIN3);
+ PINCTRL_ADD_DEVICE(SD0);
+ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_WIFI);
+ PINCTRL_ADD_DEVICE(SD1);
+ PINCTRL_ADD_DEVICE(SD1_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_WIFI);
+ PINCTRL_ADD_DEVICE(SENSOR_CLK);
+ PINCTRL_ADD_DEVICE(SSI0);
+ PINCTRL_ADD_DEVICE(SSI0_4BIT);
+ PINCTRL_ADD_DEVICE(SSI1);
+ PINCTRL_ADD_DEVICE(SSI2);
+ PINCTRL_ADD_DEVICE(UART0);
+ PINCTRL_ADD_DEVICE(UART1);
+ PINCTRL_ADD_DEVICE(UART2);
+ PINCTRL_ADD_DEVICE(USB);
+ PINCTRL_ADD_DEVICE(GPIO0);
+ PINCTRL_ADD_DEVICE(GPIO1);
+ PINCTRL_ADD_DEVICE(GPIO2);
+ PINCTRL_ADD_DEVICE(GPIO3);
+ PINCTRL_ADD_DEVICE(GPIO4);
+ PINCTRL_ADD_DEVICE(GPIO5);
+ PINCTRL_ADD_DEVICE(GPIO6);
+ PINCTRL_ADD_DEVICE(GPIO7);
+ PINCTRL_ADD_DEVICE(GPIO8);
+ PINCTRL_ADD_DEVICE(GPIO9);
+ PINCTRL_ADD_DEVICE(GPIO10);
+ PINCTRL_ADD_DEVICE(GPIO11);
+ PINCTRL_ADD_DEVICE(GPIO12);
+ PINCTRL_ADD_DEVICE(GPIO13);
+ PINCTRL_ADD_DEVICE(GPIO14);
+ PINCTRL_ADD_DEVICE(GPIO15);
+ PINCTRL_ADD_DEVICE(GPIO16);
+ PINCTRL_ADD_DEVICE(GPIO17);
+ PINCTRL_ADD_DEVICE(GPIO18);
+ PINCTRL_ADD_DEVICE(GPIO19);
+ PINCTRL_ADD_DEVICE(GPIO20);
+ PINCTRL_ADD_DEVICE(GPIO21);
+ PINCTRL_ADD_DEVICE(GPIO22);
+ PINCTRL_ADD_DEVICE(GPIO23);
+ PINCTRL_ADD_DEVICE(GPIO24);
+ PINCTRL_ADD_DEVICE(GPIO25);
+ PINCTRL_ADD_DEVICE(GPIO26);
+ PINCTRL_ADD_DEVICE(GPIO27);
+ PINCTRL_ADD_DEVICE(GPIO28);
+ PINCTRL_ADD_DEVICE(GPIO29);
+ PINCTRL_ADD_DEVICE(GPIO30);
+ PINCTRL_ADD_DEVICE(GPIO31);
+ PINCTRL_ADD_DEVICE(GPIO32);
+ PINCTRL_ADD_DEVICE(GPIO33);
+ PINCTRL_ADD_DEVICE(GPIO34);
+ PINCTRL_ADD_DEVICE(GPIO35);
+ PINCTRL_ADD_DEVICE(GPIO36);
+ PINCTRL_ADD_DEVICE(GPIO37);
+ PINCTRL_ADD_DEVICE(GPIO38);
+ PINCTRL_ADD_DEVICE(GPIO39);
+ PINCTRL_ADD_DEVICE(GPIO40);
+ PINCTRL_ADD_DEVICE(GPIO41);
+ PINCTRL_ADD_DEVICE(GPIO42);
+ PINCTRL_ADD_DEVICE(GPIO43);
+ PINCTRL_ADD_DEVICE(GPIO44);
+ PINCTRL_ADD_DEVICE(GPIO45);
+ PINCTRL_ADD_DEVICE(GPIO46);
+ PINCTRL_ADD_DEVICE(GPIO47);
+ PINCTRL_ADD_DEVICE(GPIO48);
+ PINCTRL_ADD_DEVICE(GPIO49);
+ PINCTRL_ADD_DEVICE(GPIO50);
+ PINCTRL_ADD_DEVICE(GPIO51);
+ PINCTRL_ADD_DEVICE(GPIO52);
+ PINCTRL_ADD_DEVICE(GPIO53);
+ PINCTRL_ADD_DEVICE(GPIO54);
+ PINCTRL_ADD_DEVICE(GPIO55);
+ PINCTRL_ADD_DEVICE(GPIO56);
+ PINCTRL_ADD_DEVICE(GPIO57);
+ PINCTRL_ADD_DEVICE(GPIO58);
+ PINCTRL_ADD_DEVICE(GPIO59);
+ PINCTRL_ADD_DEVICE(GPIO60);
+ PINCTRL_ADD_DEVICE(GPIO61);
+ PINCTRL_ADD_DEVICE(GPIO62);
+ PINCTRL_ADD_DEVICE(GPIO63);
+
+ PINCTRL_ADD_DEVICE(SD1_EMMC);
+}
+
+char *fh_pinctrl_selected_devices[] =
+{
+ CONFIG_PINCTRL_SELECT
+};
diff --git a/arch/arm/mach-fh/fh8858v210/Makefile b/arch/arm/mach-fh/fh8858v210/Makefile
new file mode 100644
index 00000000..1443fdae
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v210/Makefile
@@ -0,0 +1 @@
+obj-y += board.o chip.o
\ No newline at end of file
diff --git a/arch/arm/mach-fh/fh8858v210/board.c b/arch/arm/mach-fh/fh8858v210/board.c
new file mode 100644
index 00000000..bc3e265a
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v210/board.c
@@ -0,0 +1,1123 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/phy.h>
+#include <linux/dma-mapping.h>
+#include <linux/spi/eeprom.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/if_alg.h>
+#include <linux/mmc/host.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/io.h>
+#include <mach/board_config.h>
+#include <mach/pinctrl.h>
+#include <mach/clock.h>
+#include <mach/fh_uart_plat.h>
+#include <mach/fh_mci_plat.h>
+#include <mach/fh_gmac_plat.h>
+#include <mach/fh_gpio_plat.h>
+#include <mach/fh_efuse_plat.h>
+#include <mach/fh_dma_plat.h>
+#include <mach/fh_spi_plat.h>
+#include <mach/fh_i2s_plat.h>
+#include <mach/fh_pwm_plat.h>
+#include <mach/fh_wdt_plat.h>
+#include <mach/fh_usb_plat.h>
+#include <mach/fh_sadc_plat.h>
+#include <mach/fh_rtc_plat.h>
+#include "chip.h"
+
+struct uart_port fh_serial_ports[FH_UART_NUMBER];
+
+static struct map_desc fh8858v210_io_desc[] = {
+ {
+ .virtual = VA_RAM_REG_BASE,
+ .pfn = __phys_to_pfn(RAM_BASE),
+ .length = SZ_16K,
+ .type = MT_MEMORY_RWX,
+ },
+ {
+ .virtual = VA_DDRC_REG_BASE,
+ .pfn = __phys_to_pfn(DDRC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_INTC_REG_BASE,
+ .pfn = __phys_to_pfn(INTC_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_TIMER_REG_BASE,
+ .pfn = __phys_to_pfn(TIMER_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_PMU_REG_BASE,
+ .pfn = __phys_to_pfn(PMU_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART0_REG_BASE,
+ .pfn = __phys_to_pfn(UART0_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART1_REG_BASE,
+ .pfn = __phys_to_pfn(UART1_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+ {
+ .virtual = VA_UART2_REG_BASE,
+ .pfn = __phys_to_pfn(UART2_REG_BASE),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+
+};
+
+static struct resource fh_gpio0_resources[] = {
+ {
+ .start = GPIO0_REG_BASE,
+ .end = GPIO0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO0_IRQ,
+ .end = GPIO0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gpio1_resources[] = {
+ {
+ .start = GPIO1_REG_BASE,
+ .end = GPIO1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GPIO1_IRQ,
+ .end = GPIO1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart0_resources[] = {
+ {
+ .start = (UART0_REG_BASE),
+ .end = (UART0_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = UART0_IRQ,
+ .end = UART0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_uart1_resources[] = {
+ {
+ .start = (UART1_REG_BASE),
+ .end = (UART1_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART1_IRQ,
+ .end = UART1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_uart2_resources[] = {
+ {
+ .start = (UART2_REG_BASE),
+ .end = (UART2_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = UART2_IRQ,
+ .end = UART2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+static struct resource fh_sdc0_resources[] = {
+ {
+ .start = SDC0_REG_BASE,
+ .end = SDC0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC0_IRQ,
+ .end = SDC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_sdc1_resources[] = {
+ {
+ .start = SDC1_REG_BASE,
+ .end = SDC1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SDC1_IRQ,
+ .end = SDC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_gmac_resources[] = {
+ {
+ .start = GMAC_REG_BASE,
+ .end = GMAC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = GMAC_IRQ,
+ .end = GMAC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource fh_wdt_resources[] = {
+ {
+ .start = WDT_REG_BASE,
+ .end = WDT_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = WDT_IRQ,
+ .end = WDT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct resource fh_perf_resources[] = {
+ {
+ .start = PMU_REG_BASE,
+ .end = PMU_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PERF_IRQ,
+ .end = PERF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+#endif
+
+
+static struct fh_gmac_platform_data fh_gmac_data = {
+ .phy_reset_pin = 29,
+};
+
+static struct fh_uart_dma uart1_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART1_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART1_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART1_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART1_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+static struct fh_uart_dma uart2_dma_info = {
+#ifdef CONFIG_UART_TX_DMA
+ .tx_hs_no = UART2_TX_HW_HANDSHAKE,
+ .tx_dma_channel = UART2_DMA_TX_CHAN,
+#endif
+ .rx_hs_no = UART2_RX_HW_HANDSHAKE,
+ .rx_dma_channel = UART2_DMA_RX_CHAN,
+ .rx_xmit_len = 16,
+};
+
+
+static struct fh_platform_uart fh_uart_platform_data[] = {
+ {
+ .mapbase = UART0_REG_BASE,
+ .fifo_size = 16,
+ .irq = UART0_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = NULL,
+ },
+ {
+ .mapbase = UART1_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART1_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart1_dma_info,
+ },
+ {
+ .mapbase = UART2_REG_BASE,
+ .fifo_size = 32,
+ .irq = UART2_IRQ,
+ .uartclk = 16666667,
+ .use_dma = 0,
+ .dma_info = &uart2_dma_info,
+ },
+};
+
+static struct resource fh_pwm_resources[] = {
+ {
+ .start = PWM_REG_BASE,
+ .end = PWM_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = PWM_IRQ,
+ .end = PWM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_i2c_resources_0[] = {
+ {
+ .start = I2C0_REG_BASE,
+ .end = I2C0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C0_IRQ,
+ .end = I2C0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_1[] = {
+ {
+ .start = I2C1_REG_BASE,
+ .end = I2C1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C1_IRQ,
+ .end = I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_i2c_resources_2[] = {
+ {
+ .start = I2C2_REG_BASE,
+ .end = I2C2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = I2C2_IRQ,
+ .end = I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static struct resource fh_rtc_resources[] = {
+ {
+ .start = RTC_REG_BASE,
+ .end = RTC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = RTC_IRQ,
+ .end = RTC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio0_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO0",
+ .base = 0,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_gpio_chip fh_gpio1_chip = {
+ .chip = {
+ .owner = THIS_MODULE,
+ .label = "FH_GPIO1",
+ .base = 32,
+ .ngpio = 32,
+ },
+};
+
+static struct fh_pwm_data pwm_data = {
+ .npwm = 12,
+};
+
+static struct resource fh_sadc_resources[] = {
+ {
+ .start = SADC_REG_BASE,
+ .end = SADC_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SADC_IRQ,
+ .end = SADC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_aes_resources[] = {
+ {
+ .start = AES_REG_BASE,
+ .end = AES_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = AES_IRQ,
+ .end = AES_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_efuse_resources[] = {
+ {
+ .start = EFUSE_REG_BASE,
+ .end = EFUSE_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+
+static struct resource fh_axi_dma_resources[] = {
+ {
+ .start = (DMAC_REG_BASE),
+ .end = (DMAC_REG_BASE) + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = DMAC0_IRQ,
+ .end = DMAC0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+
+static struct resource fh_spi0_resources[] = {
+ {
+ .start = SPI0_REG_BASE,
+ .end = SPI0_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI0_IRQ,
+ .end = SPI0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi1_resources[] = {
+ {
+ .start = SPI1_REG_BASE,
+ .end = SPI1_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SPI1_IRQ,
+ .end = SPI1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource fh_spi2_resources[] = {
+ {
+ .start = SPI2_REG_BASE,
+ .end = SPI2_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "fh spi2 mem",
+ },
+ {
+ .start = SPI2_IRQ,
+ .end = SPI2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ .name = "fh spi2 irq",
+ },
+};
+
+static struct resource fh_usb_resources[] = {
+ {
+ .start = USBC_REG_BASE,
+ .end = USBC_REG_BASE + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = USBC_IRQ,
+ .end = USBC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+static unsigned int fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+
+struct fh_mci_board fh_mci = {
+ .num_slots = 1,
+ .get_cd = fh_mci_sys_card_detect_fixed,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+ .rescan_max_num = 2,
+};
+
+struct fh_mci_board fh_mci_sd = {
+ .num_slots = 1,
+ .bus_hz = 50000000,
+ .detect_delay_ms = 200,
+ .caps = MMC_CAP_4_BIT_DATA,
+ /*8:180 degree*/
+ .drv_degree = 8,
+ .sam_degree = 0,
+};
+
+static struct platform_device fh_gmac_device = {
+ .name = "fh_gmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gmac_resources),
+ .resource = fh_gmac_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_gmac_data,
+ },
+};
+
+struct platform_device fh_sd0_device = {
+ .name = "fh_mci",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sdc0_resources),
+ .resource = fh_sdc0_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci_sd,
+ }
+};
+
+struct platform_device fh_sd1_device = {
+ .name = "fh_mci",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_sdc1_resources),
+ .resource = fh_sdc1_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &fh_mci,
+ }
+};
+
+struct fh_sadc_platform_data fh_sadc_data = {
+ .ref_vol = 1800,
+ .active_bit = 0xfff,
+};
+
+static struct platform_device fh_sadc_device = {
+ .name = "fh_sadc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_sadc_resources),
+ .resource = fh_sadc_resources,
+ .dev = {
+ .platform_data = &fh_sadc_data,
+ },
+};
+
+static struct platform_device fh_uart0_device = {
+ .name = "ttyS",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_uart0_resources),
+ .resource = fh_uart0_resources,
+ .dev.platform_data = &fh_uart_platform_data[0],
+};
+
+static struct platform_device fh_uart1_device = {
+ .name = "ttyS",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_uart1_resources),
+ .resource = fh_uart1_resources,
+ .dev.platform_data = &fh_uart_platform_data[1],
+};
+
+static struct platform_device fh_uart2_device = {
+ .name = "ttyS",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_uart2_resources),
+ .resource = fh_uart2_resources,
+ .dev.platform_data = &fh_uart_platform_data[2],
+};
+
+static struct platform_device fh_pinctrl_device = {
+ .name = "fh_pinctrl",
+ .id = 0,
+};
+
+static struct platform_device fh_i2c0_device = {
+ .name = "fh_i2c",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_0),
+ .resource = fh_i2c_resources_0,
+};
+
+static struct platform_device fh_i2c1_device = {
+ .name = "fh_i2c",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_1),
+ .resource = fh_i2c_resources_1,
+};
+
+static struct platform_device fh_i2c2_device = {
+ .name = "fh_i2c",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(fh_i2c_resources_2),
+ .resource = fh_i2c_resources_2,
+};
+
+static struct fh_rtc_plat_data rtc_plat_data[] = {
+ {
+ .lut_cof = 58,
+ .lut_offset = 0xff,
+ .tsensor_cp_default_out = 0x993,
+ .clk_name = "rtc_hclk_gate",
+ },
+ {
+ .lut_cof = 71,
+ .lut_offset = 0xf6,
+ .tsensor_cp_default_out = 0x9cc,
+ .clk_name = "rtc_hclk_gate",
+ }
+};
+
+static struct platform_device fh_rtc_device = {
+ .name = "fh_rtc",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_rtc_resources),
+ .resource = fh_rtc_resources,
+ .dev.platform_data = &rtc_plat_data[0],
+};
+
+static struct resource fh_i2s_resources[] = {
+ {
+ .start = I2S_REG_BASE,
+ .end = I2S_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ACW_REG_BASE,
+ .end = ACW_REG_BASE + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = I2S0_IRQ,
+ .end = I2S0_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct fh_i2s_platform_data fh_i2s_data = {
+ .dma_capture_channel = 4,
+ .dma_playback_channel = 5,
+ .dma_master = 0,
+ .dma_rx_hs_num = 10,
+ .dma_tx_hs_num = 11,
+ .clk = "i2s_clk",
+ .acodec_mclk = "ac_clk",
+};
+
+static struct platform_device fh_i2s_device = {
+ .name = "fh_audio",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_i2s_resources),
+ .resource = fh_i2s_resources,
+ .dev = {
+ .platform_data = &fh_i2s_data,
+ },
+};
+
+static struct platform_device fh_gpio0_device = {
+ .name = GPIO_NAME,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_gpio0_resources),
+ .resource = fh_gpio0_resources,
+ .dev = {
+ .platform_data = &fh_gpio0_chip,
+ },
+};
+
+static struct platform_device fh_gpio1_device = {
+ .name = GPIO_NAME,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_gpio1_resources),
+ .resource = fh_gpio1_resources,
+ .dev = {
+ .platform_data = &fh_gpio1_chip,
+ },
+};
+
+static struct platform_device fh_aes_device = {
+ .name = "fh_aes",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_aes_resources),
+ .resource = fh_aes_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+
+struct fh_efuse_platform_data fh_efuse_plat_data = {
+ .efuse_support_flag = CRYPTO_CPU_SET_KEY |
+ CRYPTO_EX_MEM_SET_KEY |
+ CRYPTO_EX_MEM_SWITCH_KEY |
+ CRYPTO_EX_MEM_4_ENTRY_1_KEY |
+ CRYPTO_EX_MEM_INDEP_POWER,
+};
+
+
+
+#define FH_SPI0_CS0 (6)
+#define FH_SPI0_CS1 (55)
+
+#define FH_SPI1_CS0 (14)
+#define FH_SPI1_CS1 (57)
+
+#define SPI0_FIFO_DEPTH (128)
+#define SPI0_CLK_IN (200000000)
+#define SPI0_MAX_SLAVE_NO (2)
+#define SPI0_DMA_RX_CHANNEL (0)
+#define SPI0_DMA_TX_CHANNEL (1)
+
+#define SPI1_FIFO_DEPTH (64)
+#define SPI1_CLK_IN (100000000)
+#define SPI1_MAX_SLAVE_NO (2)
+#define SPI1_DMA_RX_CHANNEL (2)
+#define SPI1_DMA_TX_CHANNEL (3)
+
+#define SPI2_CLK_IN (100000000)
+
+/* SPI_TRANSFER_USE_DMA */
+static struct fh_spi_platform_data fh_spi0_data = {
+ .bus_no = 0,
+ .apb_clock_in = SPI0_CLK_IN,
+ .clock_source = {100000000, 150000000, 200000000},
+ .clock_source_num = 3,
+ .slave_max_num = SPI0_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI0_CS0,
+ .cs_data[0].name = "spi0_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI0_CS1,
+ .cs_data[1].name = "spi0_cs1",
+ .clk_name = "spi0_clk",
+ .dma_transfer_enable = SPI_TRANSFER_USE_DMA,
+ .rx_dma_channel = SPI0_DMA_RX_CHANNEL,
+ .rx_handshake_num = 4,
+ /*dma use inc mode could move data by burst mode...*/
+ /*or move data use single mode with low efficient*/
+ .ctl_wire_support = ONE_WIRE_SUPPORT | DUAL_WIRE_SUPPORT |
+ MULTI_WIRE_SUPPORT,
+};
+
+static struct fh_spi_platform_data fh_spi1_data = {
+ .bus_no = 1,
+ .apb_clock_in = SPI1_CLK_IN,
+ .clock_source = {SPI1_CLK_IN},
+ .clock_source_num = 1,
+ .slave_max_num = SPI1_MAX_SLAVE_NO,
+ .cs_data[0].GPIO_Pin = FH_SPI1_CS0,
+ .cs_data[0].name = "spi1_cs0",
+ .cs_data[1].GPIO_Pin = FH_SPI1_CS1,
+ .cs_data[1].name = "spi1_cs1",
+ .clk_name = "spi1_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct fh_spi_platform_data fh_spi2_data = {
+ .apb_clock_in = SPI2_CLK_IN,
+ .dma_transfer_enable = 0,
+ .rx_handshake_num = 12,
+ .clk_name = "spi2_clk",
+ .ctl_wire_support = 0,
+};
+
+static struct platform_device fh_efuse_device = {
+ .name = "fh_efuse",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_efuse_resources),
+ .resource = fh_efuse_resources,
+ .dev = {
+ .platform_data = &fh_efuse_plat_data,
+ },
+};
+
+struct fh_axi_dma_platform_data axi_dma_plat_data = {
+ .chan_priority = CHAN_PRIORITY_ASCENDING,
+ .clk_name = "ahb_clk",
+};
+
+static struct platform_device fh_axi_dma_device = {
+ .name = "fh_axi_dmac",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_axi_dma_resources),
+ .resource = fh_axi_dma_resources,
+ .dev = {
+ .platform_data = &axi_dma_plat_data,
+ },
+};
+
+static struct platform_device fh_spi0_device = {
+ .name = "fh_spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi0_resources),
+ .resource = fh_spi0_resources,
+ .dev = {
+ .platform_data = &fh_spi0_data,
+ },
+};
+
+static struct platform_device fh_spi1_device = {
+ .name = "fh_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(fh_spi1_resources),
+ .resource = fh_spi1_resources,
+ .dev = {
+ .platform_data = &fh_spi1_data,
+ },
+};
+
+static struct platform_device fh_spi2_device = {
+ .name = "fh_spi_slave",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_spi2_resources),
+ .resource = fh_spi2_resources,
+ .dev = {
+ .platform_data = &fh_spi2_data,
+ },
+};
+
+#ifdef CONFIG_FH_PERF_MON
+static struct platform_device fh_perf_device = {
+ .name = "fh_perf_mon",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_perf_resources),
+ .resource = fh_perf_resources,
+ .dev = {
+ .platform_data = NULL,
+ },
+};
+#endif
+
+
+static struct fh_wdt_platform_data fh_wdt_data = {
+ .mode = MODE_DISCRETE,
+};
+
+struct platform_device fh_wdt_device = {
+ .name = "fh_wdt",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_wdt_resources),
+ .resource = fh_wdt_resources,
+ .dev = {
+ .platform_data = &fh_wdt_data,
+ }
+};
+
+static struct platform_device fh_pwm_device = {
+ .name = "fh_pwm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_pwm_resources),
+ .resource = fh_pwm_resources,
+ .dev = {
+ .platform_data = &pwm_data,
+ },
+};
+
+static struct fh_usb_platform_data fh_usb_data = {
+ .dr_mode = "host",
+ .vbus_pwren = 47,
+};
+
+struct platform_device fh_usb_device = {
+ .name = "fh_usb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(fh_usb_resources),
+ .resource = fh_usb_resources,
+ .dev = {
+ .platform_data = &fh_usb_data,
+ }
+};
+
+#ifdef CONFIG_FH_TSENSOR
+struct platform_device fh_tsensor_device = {
+ .name = "fh_tsensor",
+ .id = 0,
+};
+#endif
+
+static struct platform_device *fh8858v210_devices[] __initdata = {
+ &fh_uart0_device,
+ &fh_uart1_device,
+ &fh_uart2_device,
+ &fh_pinctrl_device,
+ &fh_i2c0_device,
+ &fh_i2c1_device,
+ &fh_i2c2_device,
+ &fh_rtc_device,
+ &fh_sd0_device,
+ &fh_sd1_device,
+ &fh_sadc_device,
+ &fh_gmac_device,
+ &fh_gpio0_device,
+ &fh_gpio1_device,
+ &fh_aes_device,
+ &fh_efuse_device,
+ &fh_axi_dma_device,
+ &fh_spi0_device,
+ &fh_spi1_device,
+ &fh_spi2_device,
+ &fh_i2s_device,
+ &fh_pwm_device,
+ &fh_wdt_device,
+ &fh_usb_device,
+#ifdef CONFIG_FH_PERF_MON
+ &fh_perf_device,
+#endif
+#ifdef CONFIG_FH_TSENSOR
+ &fh_tsensor_device,
+#endif
+};
+
+static struct mtd_partition fh_sf_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* Ramboot & U-Boot environment */
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ /* U-Boot */
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi_flash:256k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),4M(kernel),
+ * 8M(rootfs),
+ * -(app) */
+ /* two blocks with bad block table (and mirror) at the end */
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct mtd_partition fh_sf_nand_parts[] = {
+ {
+ /* head & Ramboot */
+ .name = "bootstrap",
+ .offset = 0,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ }, {
+ .name = "uboot-env",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_256K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "uboot",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_512K,
+ .mask_flags = MTD_WRITEABLE,
+ }, {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ }, {
+ .name = "rootfs",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_8M,
+ .mask_flags = 0,
+ }, {
+ .name = "app",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* mtdparts=
+ * spi0.0:64k(bootstrap),
+ * 64k(u-boot-env),
+ * 192k(u-boot),
+ * 4M(kernel),
+ * 8M(rootfs),
+ * -(app)
+ * two blocks with bad block table (and mirror) at the end
+ */
+};
+#endif
+
+static struct flash_platform_data fh_flash_platform_data = {
+ .name = "spi_flash",
+ .parts = fh_sf_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_parts),
+};
+#ifdef CONFIG_MTD_SPI_NAND
+static struct flash_platform_data fh_nandflash_platform_data = {
+ .name = "spi_nandflash",
+ .parts = fh_sf_nand_parts,
+ .nr_parts = ARRAY_SIZE(fh_sf_nand_parts),
+};
+#endif
+
+static struct spi_board_info fh_spi_devices[] = {
+#ifdef CONFIG_MTD_SPI_NAND
+ {
+ .modalias = "spi-nand",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 50000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &fh_nandflash_platform_data,
+ },
+#endif
+ {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ /* multi wire should adapt spi para 'ctl_wire_support'*/
+ .mode = SPI_MODE_3 | SPI_RX_DUAL,
+ .max_speed_hz = 50000000,
+ .platform_data = &fh_flash_platform_data,
+ },
+
+};
+
+extern void early_print(const char *str, ...);
+
+static void __init fh_console_pre_init(struct fh_platform_uart *plat, int num)
+{
+ int idx = 0;
+
+ for (; idx < num; idx++) {
+ struct uart_port *port;
+
+ port = &fh_serial_ports[idx];
+ port->mapbase = plat[idx].mapbase;
+ port->fifosize = plat[idx].fifo_size;
+ port->uartclk = plat[idx].uartclk;
+
+ switch (idx) {
+ case 0:
+ port->membase = (unsigned char *)VA_UART0_REG_BASE;
+ break;
+ case 1:
+ port->membase = (unsigned char *)VA_UART1_REG_BASE;
+ break;
+ case 2:
+ port->membase = (unsigned char *)VA_UART2_REG_BASE;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void __init fh8858v210_map_io(void)
+{
+ iotable_init(fh8858v210_io_desc, ARRAY_SIZE(fh8858v210_io_desc));
+ fh_console_pre_init(fh_uart_platform_data,
+ ARRAY_SIZE(fh_uart_platform_data));
+}
+
+
+static __init void fh8858v210_board_init(void)
+{
+ if (fh_is_8858v210())
+ fh_rtc_device.dev.platform_data = &rtc_plat_data[1];
+ platform_add_devices(fh8858v210_devices,
+ ARRAY_SIZE(fh8858v210_devices));
+ spi_register_board_info(fh_spi_devices, ARRAY_SIZE(fh_spi_devices));
+}
+void __init fh_timer_init_no_of(unsigned int iovbase,
+ unsigned int irqno);
+
+static void __init fh8858v210_init_early(void)
+{
+ fh_pmu_init();
+ fh_pinctrl_init(VA_PMU_REG_BASE + 0x80);
+}
+
+static void __init fh_time_init(void)
+{
+ unsigned int vtimerbase = (unsigned int)ioremap(TIMER_REG_BASE, SZ_4K);
+
+ fh_clk_init();
+ fh_timer_init_no_of(vtimerbase, TMR0_IRQ);
+
+}
+
+void __init fh_intc_init_no_of(unsigned int iovbase);
+static void __init fh_intc_init(void)
+{
+ unsigned int vintcbase = (unsigned int)ioremap(INTC_REG_BASE, SZ_4K);
+
+ fh_intc_init_no_of(vintcbase);
+
+}
+static void fh8858v210_restart
+ (enum reboot_mode mode, const char *cmd)
+{
+ fh_pmu_restart();
+}
+
+
+MACHINE_START(FH8858V210, "FH8858V210")
+ .atag_offset = 0x100,
+ .map_io = fh8858v210_map_io,
+ .init_irq = fh_intc_init,
+ .init_time = fh_time_init,
+ .init_machine = fh8858v210_board_init,
+ .init_early = fh8858v210_init_early,
+ .restart = fh8858v210_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-fh/fh8858v210/board_config.fh8858v210.appboard b/arch/arm/mach-fh/fh8858v210/board_config.fh8858v210.appboard
new file mode 100644
index 00000000..335a1304
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v210/board_config.fh8858v210.appboard
@@ -0,0 +1,45 @@
+#ifndef BOARD_CONFIG_H_
+#define BOARD_CONFIG_H_
+
+/*
+ * GPIO0 -> IRCUT_ON
+ * GPIO1 -> IRCUT_OFF
+ * GPIO2 -> USB_PWREN
+ * GPIO11 -> EMAC PHY Reset
+ * GPIO12 -> CIS_CLK
+ * GPIO13 -> CIS_RSTN
+ * GPIO14 -> CIS_PDN
+ * GPIO19 -> SD1_PWREN/WIFI_REG_ON
+ * GPIO20 -> AK7755 Reset
+ * GPIO24 -> LED0
+ * GPIO25 -> LED1
+ * GPIO26 -> Reset Configs
+ * GPIO27 -> AK7755 PowerDown
+ * GPIO28 -> IR
+ * GPIO53 -> USB_PWREN/SD0_PWREN
+ * GPIO55 -> SD1 WIFI Interrupt
+ */
+
+#define CONFIG_SD_CD_FIXED
+
+#define CONFIG_ISP_CLK_RATE 200000000
+#define CONFIG_JPEG_CLK_RATE 200000000
+#define CONFIG_VEU_CLK_RATE 300000000
+
+#define USB_VBUS_PWR_GPIO (47)
+
+#define ETH_GPIO "ETH", "GPIO48", "GPIO49", "GPIO50", "GPIO51", "GPIO52",\
+ "GPIO53", "GPIO54", "GPIO55", "GPIO56"
+
+#define CONFIG_PINCTRL_SELECT \
+ "I2C0", "PWM2", "PWM3", "PWM4", "PWM5", "PWM6", "PWM7", \
+ "PWM8", "PWM9", "SADC_XAIN0", "SADC_XAIN1", \
+ "SADC_XAIN2", "SADC_XAIN3", "SD0_NO_WP", "SD1_NO_WP", \
+ "SENSOR_CLK", "SSI0_4BIT", "UART0", "UART1", "GPIO4", \
+ "GPIO13", "GPIO14", "GPIO15", ETH_GPIO, \
+ "GPIO30", "GPIO31", "GPIO32", "GPIO43", "GPIO44", \
+ "GPIO47", \
+\
+ "GPIO11", "GPIO16", "GPIO45", "GPIO46"
+
+#endif /* BOARD_CONFIG_H_ */
diff --git a/arch/arm/mach-fh/fh8858v210/chip.c b/arch/arm/mach-fh/fh8858v210/chip.c
new file mode 100644
index 00000000..9bbb3c49
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v210/chip.c
@@ -0,0 +1,747 @@
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <asm/mach/map.h>
+#include <mach/pmu.h>
+#include <mach/clock.h>
+#include <mach/board_config.h>
+
+/*
+ * external oscillator
+ * fixed to 24M
+ */
+static struct fh_clk osc_clk = {
+ .name = "osc_clk",
+ .frequency = OSC_FREQUENCY,
+ .flag = CLOCK_FIXED,
+};
+
+/*
+ * phase-locked-loop device,
+ * generates a higher frequency clock
+ * from the external oscillator reference
+ *PLL_DDR
+ */
+
+static struct fh_clk pll_ddr_rclk = {
+ .name = "pll_ddr_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL0,
+ .en_reg_offset = REG_PMU_PLL0_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_CPU*/
+static struct fh_clk pll_cpu_pclk = {
+ .name = "pll_cpu_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+static struct fh_clk pll_cpu_rclk = {
+ .name = "pll_cpu_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL1,
+ .en_reg_offset = REG_PMU_PLL1_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+/*PLL_SYS*/
+static struct fh_clk pll_sys_pclk = {
+ .name = "pll_sys_pclk",
+ .flag = CLOCK_PLL_P|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf00,
+};
+
+
+static struct fh_clk pll_sys_rclk = {
+ .name = "pll_sys_rclk",
+ .flag = CLOCK_PLL_R|CLOCK_NOGATE,
+ .parent = {&osc_clk},
+ .div_reg_offset = REG_PMU_PLL2,
+ .en_reg_offset = REG_PMU_PLL2_CTRL,
+ .en_reg_mask = 0xf000,
+};
+
+static struct fh_clk pllsysp_div12_clk = {
+ .name = "pllsysp_div12_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk ddr_clk = {
+ .name = "ddr_clk",
+ .flag = CLOCK_NODIV,
+ .parent = {&pll_ddr_rclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8,
+};
+static struct fh_clk arm_clk = {
+ .name = "arm_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NOGATE|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1,
+};
+static struct fh_clk arc_clk = {
+ .name = "arc_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NODIV,
+ .parent = {&osc_clk, &pll_cpu_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400000,
+};
+static struct fh_clk ahb_clk = {
+ .name = "ahb_clk",
+ .flag = CLOCK_MULTI_PARENT|CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&osc_clk, &pll_sys_pclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf0000,
+};
+
+static struct fh_clk isp_aclk = {
+ .name = "isp_aclk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1,
+ .def_rate = CONFIG_ISP_CLK_RATE,
+};
+static struct fh_clk ispb_aclk = {
+ .name = "ispb_aclk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4,
+};
+
+static struct fh_clk vpu_clk = {
+ .name = "vpu_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&isp_aclk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80000000,
+};
+
+static struct fh_clk pix_clk = {
+ .name = "pix_clk",
+ .flag = CLOCK_NORESET|CLOCK_NOGATE,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0xf000000,
+};
+
+static struct fh_clk jpeg_clk = {
+ .name = "jpeg_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x40000000,
+ .def_rate = CONFIG_JPEG_CLK_RATE,
+};
+
+static struct fh_clk bgm_clk = {
+ .name = "bgm_clk",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0xf00000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x40000,
+};
+
+static struct fh_clk jpeg_adapt_clk = {
+ .name = "jpeg_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&jpeg_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2,
+};
+static struct fh_clk spi0_clk = {
+ .name = "spi0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100,
+};
+static struct fh_clk sdc0_clk = {
+ .name = "sdc0_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x4,
+};
+static struct fh_clk spi2_clk = {
+ .name = "spi2_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x100000,
+};
+static struct fh_clk spi1_clk = {
+ .name = "spi1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x200,
+};
+static struct fh_clk sdc1_clk = {
+ .name = "sdc1_clk",
+ .parent = {&pll_sys_pclk},
+ .prediv = 8,
+ .div_reg_offset = REG_PMU_CLK_DIV3,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x400,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x2,
+};
+
+static struct fh_clk veu_clk = {
+ .name = "veu_clk",
+ .flag = CLOCK_MULTI_PARENT,
+ .parent = {&pll_sys_pclk, &pll_sys_rclk},
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_SYS_CTRL,
+ .sel_reg_mask = 0x4,
+ .div_reg_offset = REG_PMU_CLK_DIV0,
+ .div_reg_mask = 0x7000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000000,
+ .def_rate = CONFIG_VEU_CLK_RATE,
+
+};
+
+static struct fh_clk veu_adapt_clk = {
+ .name = "veu_adapt_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&veu_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000000,
+
+};
+
+static struct fh_clk cis_clk_out = {
+ .name = "cis_clk_out",
+ .flag = CLOCK_NORESET,
+ .parent = {&pll_sys_pclk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800000,
+};
+
+static struct fh_clk eth_clk = {
+ .name = "eth_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0xf000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x12000000,
+ .rst_reg_offset = REG_PMU_SWRST_AHB_CTRL,
+ .rst_reg_mask = 0x20000,
+};
+static struct fh_clk i2c0_clk = {
+ .name = "i2c0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x400,
+};
+
+static struct fh_clk i2c1_clk = {
+ .name = "i2c1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800,
+};
+
+static struct fh_clk i2c2_clk = {
+ .name = "i2c2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x00003f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x00000008,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20000000,
+};
+
+static struct fh_clk pwm_clk = {
+ .name = "pwm_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x10000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x80,
+ .def_rate = 50000000,
+};
+
+static struct fh_clk uart0_clk = {
+ .name = "uart0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x2000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x4000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk uart1_clk = {
+ .name = "uart1_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV4,
+ .div_reg_mask = 0x1f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000,
+ .def_rate = 16666666,
+};
+static struct fh_clk uart2_clk = {
+ .name = "uart2_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = 0,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV7,
+ .div_reg_mask = 0x7f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x8000000,
+ .def_rate = 16666666,
+};
+
+static struct fh_clk efuse_clk = {
+ .name = "efuse_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV1,
+ .div_reg_mask = 0x3f000000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x200000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x800000,
+};
+
+static struct fh_clk pts_clk = {
+ .name = "pts_clk",
+ .parent = {&pllsysp_div12_clk},
+ .flag = CLOCK_NORESET,
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV2,
+ .div_reg_mask = 0x1ff,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x80000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL2,
+ .rst_reg_mask = 0x1,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk tmr0_clk = {
+ .name = "tmr0_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x20000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x40000,
+};
+
+static struct fh_clk sadc_clk = {
+ .name = "sadc_clk",
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x7f0000,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x4000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10000,
+};
+
+static struct fh_clk ac_clk = {
+ .name = "ac_clk",
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x800,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x1000,
+};
+
+static struct fh_clk i2s_clk = {
+ .name = "i2s_clk",
+ .parent = {&ac_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV6,
+ .div_reg_mask = 0x3f00,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x1000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x2000,
+};
+
+static struct fh_clk wdt_clk = {
+ .name = "wdt_clk",
+ .flag = 0,
+ .parent = {&ahb_clk},
+ .prediv = 1,
+ .div_reg_offset = REG_PMU_CLK_DIV5,
+ .div_reg_mask = 0xff00,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8000000,
+ .rst_reg_offset = REG_PMU_SWRST_APB_CTRL,
+ .rst_reg_mask = 0x100000,
+ .def_rate = 1000000,
+};
+
+static struct fh_clk gpio0_db_clk = {
+ .name = "gpio0_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x8000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio1_db_clk = {
+ .name = "gpio1_db_clk",
+ .flag = 0,
+ .parent = {&pllsysp_div12_clk},
+ .prediv = 100,
+ .div_reg_offset = REG_PMU_CLK_DIV8,
+ .div_reg_mask = 0x7fff0000,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x80000000,
+ .rst_reg_offset = REG_PMU_SWRST_MAIN_CTRL,
+ .rst_reg_mask = 0x20,
+};
+
+
+static struct fh_clk mipi_dphy_clk = {
+ .name = "mipi_dphy_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .parent = {&osc_clk},
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE,
+ .en_reg_mask = 0x100000,
+};
+static struct fh_clk mipi_wrap_gate = {
+ .name = "mipi_wrap_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk rtc_hclk_gate = {
+ .name = "rtc_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk emac_hclk_gate = {
+ .name = "emac_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk usb_clk = {
+ .name = "usb_clk",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk aes_hclk_gate = {
+ .name = "aes_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x80,
+};
+static struct fh_clk ephy_clk_gate = {
+ .name = "ephy_clk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x1,
+};
+static struct fh_clk sdc0_clk8x_gate = {
+ .name = "sdc0_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x4,
+};
+static struct fh_clk sdc1_clk8x_gate = {
+ .name = "sdc1_clk8x_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x8,
+};
+static struct fh_clk mipic_pclk_gate = {
+ .name = "mipic_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_GATE1,
+ .en_reg_mask = 0x10,
+};
+
+static struct fh_clk gpio0_pclk_gate = {
+ .name = "gpio0_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x4000,
+};
+static struct fh_clk gpio1_pclk_gate = {
+ .name = "gpio1_pclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV8,
+ .en_reg_mask = 0x40000000,
+};
+static struct fh_clk isp_hclk_gate = {
+ .name = "isp_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x1000000,
+};
+static struct fh_clk veu_hclk_gate = {
+ .name = "veu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x2000000,
+};
+static struct fh_clk bgm_hclk_gate = {
+ .name = "bgm_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x4000000,
+};
+static struct fh_clk adapt_hclk_gate = {
+ .name = "adapt_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x8000000,
+};
+static struct fh_clk jpg_hclk_gate = {
+ .name = "jpg_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x10000000,
+};
+static struct fh_clk jpg_adapt_gate = {
+ .name = "jpg_adapt_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x20000000,
+};
+static struct fh_clk vpu_hclk_gate = {
+ .name = "vpu_hclk_gate",
+ .flag = CLOCK_NORESET|CLOCK_NODIV,
+ .prediv = 1,
+ .en_reg_offset = REG_PMU_CLK_DIV7,
+ .en_reg_mask = 0x40000000,
+};
+
+static struct fh_clk sdc0_clk_sample = {
+ .name = "sdc0_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf0000,
+};
+
+static struct fh_clk sdc0_clk_drv = {
+ .name = "sdc0_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00000,
+};
+
+static struct fh_clk sdc1_clk_sample = {
+ .name = "sdc1_clk_sample",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf00,
+};
+
+static struct fh_clk sdc1_clk_drv = {
+ .name = "sdc1_clk_drv",
+ .parent = {&sdc0_clk},
+ .flag = CLOCK_NOGATE | CLOCK_PHASE,
+ .prediv = 1,
+ .sel_reg_offset = REG_PMU_CLK_GATE1,
+ .sel_reg_mask = 0xf000,
+};
+
+struct fh_clk *fh_clks[] = {
+ &osc_clk,
+ &pll_ddr_rclk,
+ &pll_cpu_pclk,
+ &pll_cpu_rclk,
+ &pll_sys_pclk,
+ &pll_sys_rclk,
+ &arm_clk,
+ &arc_clk,
+ &ahb_clk,
+ &ddr_clk,
+ &isp_aclk,
+ &ispb_aclk,
+ &jpeg_clk,
+ &jpeg_adapt_clk,
+ &vpu_clk,
+ &veu_clk,
+ &veu_adapt_clk,
+ &bgm_clk,
+ &mipi_dphy_clk,
+ &pllsysp_div12_clk,
+ &cis_clk_out,
+ &pix_clk,
+ &pts_clk,
+ &spi0_clk,
+ &spi1_clk,
+ &spi2_clk,
+ &sdc0_clk,
+ &sdc1_clk,
+ &uart0_clk,
+ &uart1_clk,
+ &uart2_clk,
+ &i2c0_clk,
+ &i2c1_clk,
+ &i2c2_clk,
+ &pwm_clk,
+ &wdt_clk,
+ &tmr0_clk,
+ &ac_clk,
+ &i2s_clk,
+ &sadc_clk,
+ &eth_clk,
+ &efuse_clk,
+ &gpio0_db_clk,
+ &gpio1_db_clk,
+ &mipi_wrap_gate,
+ &rtc_hclk_gate,
+ &emac_hclk_gate,
+ &usb_clk,
+ &aes_hclk_gate,
+ &ephy_clk_gate,
+ &sdc0_clk8x_gate,
+ &sdc1_clk8x_gate,
+ &gpio0_pclk_gate,
+ &gpio1_pclk_gate,
+ &mipic_pclk_gate,
+ &sdc0_clk_sample,
+ &sdc0_clk_drv,
+ &sdc1_clk_sample,
+ &sdc1_clk_drv,
+ &isp_hclk_gate,
+ &veu_hclk_gate,
+ &bgm_hclk_gate,
+ &adapt_hclk_gate,
+ &jpg_hclk_gate,
+ &jpg_adapt_gate,
+ &vpu_hclk_gate,
+ NULL,
+};
+EXPORT_SYMBOL(fh_clks);
diff --git a/arch/arm/mach-fh/fh8858v210/chip.h b/arch/arm/mach-fh/fh8858v210/chip.h
new file mode 100644
index 00000000..100b92d8
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v210/chip.h
@@ -0,0 +1,421 @@
+#ifndef __ASM_ARCH_HL_H
+#define __ASM_ARCH_HL_H
+
+#include <linux/init.h>
+
+#define SRAM_GRANULARITY 32
+#define SRAM_SIZE (SZ_128K+SZ_8K)
+
+
+#define RAM_BASE (0x10000000)
+#define DDR_BASE (0xA0000000)
+
+
+#define PMU_REG_BASE (0xF0000000)
+#define TIMER_REG_BASE (0xF0C00000)
+#define GPIO0_REG_BASE (0xF0300000)
+#define GPIO1_REG_BASE (0xF4000000)
+#define UART0_REG_BASE (0xF0700000)
+#define UART1_REG_BASE (0xF0800000)
+#define SPI0_REG_BASE (0xF0500000)
+#define SPI1_REG_BASE (0xF0600000)
+#define SPI2_REG_BASE (0xF0640000)
+#define INTC_REG_BASE (0xE0200000)
+#define GMAC_REG_BASE (0xE0600000)
+#define USBC_REG_BASE (0xE0700000)
+#define DMAC_REG_BASE (0xE0300000)
+#define I2C1_REG_BASE (0xF0B00000)
+#define I2C0_REG_BASE (0xF0200000)
+#define I2C2_REG_BASE (0xF0100000)
+#define SDC0_REG_BASE (0xE2000000)
+#define SDC1_REG_BASE (0xE2200000)
+#define WDT_REG_BASE (0xF0D00000)
+#define PWM_REG_BASE (0xF0400000)
+#define I2S_REG_BASE (0xF0900000)
+#define ACW_REG_BASE (0xF0A00000)
+#define UART2_REG_BASE (0xF1300000)
+#define SADC_REG_BASE (0xF1200000)
+#define EFUSE_REG_BASE (0xF1600000)
+#define AES_REG_BASE (0xE8200000)
+#define RTC_REG_BASE (0xF1500000)
+#define DDRC_REG_BASE (0xED000000)
+#define CONSOLE_REG_BASE UART0_REG_BASE
+#define FH_UART_NUMBER 3
+
+#define FH_PMU_REG_SIZE 0x2110
+#define REG_PMU_CHIP_ID (0x0000)
+#define REG_PMU_IP_VER (0x0004)
+#define REG_PMU_FW_VER (0x0008)
+#define REG_PMU_CLK_SEL (0x000c)
+/*for HL REG_PMU_SYS_CTRL and CLK_SEL use one register */
+#define REG_PMU_SYS_CTRL (0x000c)
+#define REG_PMU_PLL0 (0x0010)
+#define REG_PMU_PLL1 (0x0014)
+#define REG_PMU_PLL0_CTRL (0x0018)
+#define REG_PMU_CLK_GATE (0x001c)
+#define REG_PMU_CLK_GATE1 (0x0020)
+#define REG_PMU_CLK_DIV0 (0x0024)
+#define REG_PMU_CLK_DIV1 (0x0028)
+#define REG_PMU_CLK_DIV2 (0x002c)
+#define REG_PMU_CLK_DIV3 (0x0030)
+#define REG_PMU_CLK_DIV4 (0x0034)
+#define REG_PMU_CLK_DIV5 (0x0038)
+#define REG_PMU_CLK_DIV6 (0x003c)
+#define REG_PMU_SWRST_MAIN_CTRL (0x0040)
+#define REG_PMU_SWRST_MAIN_CTRL2 (0x0044)
+#define REG_PMU_SWRST_AHB_CTRL (0x0048)
+#define REG_PMU_SWRST_APB_CTRL (0x004c)
+#define REG_PMU_SPC_IO_STATUS (0x0054)
+#define REG_PMU_SPC_FUN (0x0058)
+#define REG_PMU_CLK_DIV7 (0x005c)
+#define REG_PMU_CLK_DIV8 (0x0060)
+#define REG_PMU_PLL2 (0x0064)
+#define REG_PMU_PLL2_CTRL (0x0068)
+#define REG_PMU_PLL1_CTRL (0x006c)
+#define REG_PAD_PWR_SEL (0x0074)
+#define REG_PMU_SWRSTN_NSR (0x0078)
+#define REG_PMU_SWRSTN_NSR1 (0x007c)
+#define REG_PMU_ETHPHY_REG0 (0x2108)
+
+
+#define REG_PMU_PAD_BOOT_MODE_CFG (0x0080)
+#define REG_PMU_PAD_BOOT_SEL1_CFG (0x0084)
+#define REG_PMU_PAD_BOOT_SEL0_CFG (0x0088)
+#define REG_PMU_PAD_UART0_TX_CFG (0x008c)
+#define REG_PMU_PAD_UART0_RX_CFG (0x0090)
+#define REG_PMU_PAD_I2C0_SCL_CFG (0x0094)
+#define REG_PMU_PAD_I2C0_SDA_CFG (0x0098)
+#define REG_PMU_PAD_SENSOR_CLK_CFG (0x009c)
+#define REG_PMU_PAD_SENSOR_RSTN_CFG (0x00a0)
+#define REG_PMU_PAD_UART1_TX_CFG (0x00a4)
+#define REG_PMU_PAD_UART1_RX_CFG (0x00a8)
+#define REG_PMU_PAD_I2C1_SCL_CFG (0x00ac)
+#define REG_PMU_PAD_I2C1_SDA_CFG (0x00b0)
+#define REG_PMU_PAD_UART2_TX_CFG (0x00b4)
+#define REG_PMU_PAD_UART2_RX_CFG (0x00b8)
+#define REG_PMU_PAD_USB_PWREN_CFG (0x00bc)
+#define REG_PMU_PAD_PWM0_CFG (0x00c0)
+#define REG_PMU_PAD_PWM1_CFG (0x00c4)
+#define REG_PMU_PAD_PWM2_CFG (0x00c8)
+#define REG_PMU_PAD_PWM3_CFG (0x00cc)
+#define REG_PMU_PAD_MAC_RMII_CLK_CFG (0x00d0)
+#define REG_PMU_PAD_MAC_REF_CLK_CFG (0x00d4)
+#define REG_PMU_PAD_MAC_TXD0_CFG (0x00d8)
+#define REG_PMU_PAD_MAC_TXD1_CFG (0x00dc)
+#define REG_PMU_PAD_MAC_TXEN_CFG (0x00e0)
+#define REG_PMU_PAD_MAC_RXD0_CFG (0x00e4)
+#define REG_PMU_PAD_MAC_RXD1_CFG (0x00e8)
+#define REG_PMU_PAD_MAC_RXDV_CFG (0x00ec)
+#define REG_PMU_PAD_MAC_MDC_CFG (0x00f0)
+#define REG_PMU_PAD_MAC_MDIO_CFG (0x00f4)
+#define REG_PMU_PAD_SD1_CLK_CFG (0x00f8)
+#define REG_PMU_PAD_SD1_CD_CFG (0x00fc)
+#define REG_PMU_PAD_SD1_CMD_RSP_CFG (0x0100)
+#define REG_PMU_PAD_SD1_DATA_0_CFG (0x0104)
+#define REG_PMU_PAD_SD1_DATA_1_CFG (0x0108)
+#define REG_PMU_PAD_SD1_DATA_2_CFG (0x010c)
+#define REG_PMU_PAD_SD1_DATA_3_CFG (0x0110)
+#define REG_PMU_PAD_GPIO_0_CFG (0x0114)
+#define REG_PMU_PAD_GPIO_1_CFG (0x0118)
+#define REG_PMU_PAD_GPIO_2_CFG (0x011c)
+#define REG_PMU_PAD_GPIO_3_CFG (0x0120)
+#define REG_PMU_PAD_GPIO_4_CFG (0x0124)
+#define REG_PMU_PAD_SSI0_CLK_CFG (0x0128)
+#define REG_PMU_PAD_SSI0_CSN_0_CFG (0x012c)
+#define REG_PMU_PAD_SSI0_TXD_CFG (0x0130)
+#define REG_PMU_PAD_SSI0_RXD_CFG (0x0134)
+#define REG_PMU_PAD_SSI0_D2_CFG (0x0138)
+#define REG_PMU_PAD_SSI0_D3_CFG (0x013c)
+#define REG_PMU_PAD_SSI1_CLK_CFG (0x0140)
+#define REG_PMU_PAD_SSI1_CSN_0_CFG (0x0144)
+#define REG_PMU_PAD_SSI1_TXD_CFG (0x0148)
+#define REG_PMU_PAD_SSI1_RXD_CFG (0x014c)
+#define REG_PMU_PAD_SD0_CD_CFG (0x0150)
+#define REG_PMU_PAD_SD0_CLK_CFG (0x0154)
+#define REG_PMU_PAD_SD0_CMD_RSP_CFG (0x0158)
+#define REG_PMU_PAD_SD0_DATA_0_CFG (0x015c)
+#define REG_PMU_PAD_SD0_DATA_1_CFG (0x0160)
+#define REG_PMU_PAD_SD0_DATA_2_CFG (0x0164)
+#define REG_PMU_PAD_SD0_DATA_3_CFG (0x0168)
+#define REG_PMU_PAD_SADC_XAIN0_CFG (0x016c)
+#define REG_PMU_PAD_SADC_XAIN1_CFG (0x0170)
+#define REG_PMU_PAD_SADC_XAIN2_CFG (0x0174)
+#define REG_PMU_PAD_SADC_XAIN3_CFG (0x0178)
+#define REG_PMU_PAD_GPIO_28_CFG (0x017c)
+#define REG_PMU_PAD_GPIO_29_CFG (0x0180)
+
+#define REG_PMU_ARM_INT_0 (0x01e0)
+#define REG_PMU_ARM_INT_1 (0x01e4)
+#define REG_PMU_ARM_INT_2 (0x01e8)
+#define REG_PMU_A625_INT_0 (0x01ec)
+#define REG_PMU_A625_INT_1 (0x01f0)
+#define REG_PMU_A625_INT_2 (0x01f4)
+#define REG_PMU_DMA (0x01f8)
+#define REG_PMU_WDT_CTRL (0x01fc)
+#define REG_PMU_DBG_STAT0 (0x0200)
+#define REG_PMU_DBG_STAT1 (0x0204)
+#define REG_PMU_DBG_STAT2 (0x0208)
+#define REG_PMU_DBG_STAT3 (0x020c)
+#define REG_PMU_USB_SYS (0x0210)
+#define REG_PMU_USB_CFG (0x0214)
+#define REG_PMU_USB_TUNE (0x0218)
+#define REG_PMU_USB_SYS1 (0x0228)
+#define REG_PMU_PTSLO (0x022c)
+#define REG_PMU_PTSHI (0x0230)
+#define REG_PMU_USER0 (0x0234)
+#define REG_PMU_BOOT_MODE (0x0330)
+#define REG_PMU_DDR_SIZE (0x0334)
+#define REG_PMU_CHIP_INFO (0x033C)
+#define REG_PMU_EPHY_PARAM (0x0340)
+#define REG_PMU_RTC_PARAM (0x0344)
+#define REG_PMU_SD1_FUNC_SEL (0x03a0)
+#define REG_PMU_PRDCID_CTRL0 (0x0500)
+#define REG_PMU_A625BOOT0 (0x2000)
+#define REG_PMU_A625BOOT1 (0x2004)
+#define REG_PMU_A625BOOT2 (0x2008)
+#define REG_PMU_A625BOOT3 (0x200c)
+#define REG_PMU_A625_START_CTRL (0x2010)
+#define REG_PMU_ARC_INTC_MASK (0x2014)
+
+#define FH_GMAC_AHB_RESET (1<<17)
+#define FH_GMAC_SPEED_100M (1<<24)
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+#define PMU_RXDV_GPIO_SWITCH (REG_PMU_PAD_MAC_RXDV_CFG)
+#define PMU_RXDV_GPIO_MASK (0x0f000000)
+#define PMU_RXDV_GPIO_VAL (0x01000000)
+
+#define PMU_DWI2S_CLK_SEL_REG (REG_PMU_CLK_SEL)
+#define PMU_DWI2S_CLK_SEL_SHIFT (1)
+#define PMU_DWI2S_CLK_DIV_REG (REG_PMU_CLK_DIV6)
+#define PMU_DWI2S_CLK_DIV_SHIFT (0)
+
+/*ATTENTION: written by ARC */
+#define PMU_ARM_INT_MASK (0x01ec)
+#define PMU_ARM_INT_RAWSTAT (0x01f0)
+#define PMU_ARM_INT_STAT (0x01f4)
+
+#define PMU_A625_INT_MASK (0x01e0)
+#define PMU_A625_INT_RAWSTAT (0x01e4)
+#define PMU_A625_INT_STAT (0x01e8)
+
+#define PMU_IRQ 0
+#define DDRC_IRQ 1
+#define WDT_IRQ 2
+#define TMR0_IRQ 3
+#define VEU_IRQ 4
+#define PERF_IRQ 5
+#define VPU_IRQ 9
+#define I2C0_IRQ 11
+#define I2C1_IRQ 12
+#define JPEG_IRQ 13
+#define BGM_IRQ 14
+#define VEU_LOOP_IRQ 15
+#define AES_IRQ 16
+#define MIPIC_IRQ 17
+#define MIPI_WRAP_IRQ 18
+#define ACW_IRQ 19
+#define SADC_IRQ 20
+#define SPI1_IRQ 21
+#define JPEG_LOOP_IRQ 22
+#define DMAC0_IRQ 23
+#define DMAC1_IRQ 24
+#define I2S0_IRQ 25
+#define GPIO0_IRQ 26
+#define SPI0_IRQ 28
+#define ARC_SW_IRQ 29
+#define UART0_IRQ 30
+#define UART1_IRQ 31
+#define ARM_SW_IRQ 32
+#define RTC_IRQ 33
+#define PWM_IRQ 36
+#define SPI2_IRQ 38
+#define USBC_IRQ 39
+#define GPIO1_IRQ 40
+#define UART2_IRQ 41
+#define SDC0_IRQ 42
+#define SDC1_IRQ 43
+#define GMAC_IRQ 44
+#define EPHY_IRQ 45
+#define I2C2_IRQ 46
+#define RTC_ALM_IRQ 47
+#define RTC_CORE_IRQ 48
+/* because chips with some same function in different */
+/* pmu register, use wrap marco to make code to be same */
+#define PMU_RMII_SPEED_MODE (REG_PMU_CLK_SEL)
+
+#define MEM_START_PHY_ADDR DDR_BASE
+#define MEM_SIZE 0x8000000
+
+
+#define NR_INTERNAL_IRQS (64)
+#define NR_EXTERNAL_IRQS (64)
+/*#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS)*/
+
+/* SWRST_MAIN_CTRL */
+#define CPU_RSTN_BIT (0)
+#define UTMI_RSTN_BIT (1)
+#define DDRPHY_RSTN_BIT (2)
+#define DDRC_RSTN_BIT (3)
+#define GPIO0_DB_RSTN_BIT (4)
+#define GPIO1_DB_RSTN_BIT (5)
+#define PIXEL_RSTN_BIT (6)
+#define PWM_RSTN_BIT (7)
+#define SPI0_RSTN_BIT (8)
+#define SPI1_RSTN_BIT (9)
+#define I2C0_RSTN_BIT (10)
+#define I2C1_RSTN_BIT (11)
+#define ACODEC_RSTN_BIT (12)
+#define I2S_RSTN_BIT (13)
+#define UART0_RSTN_BIT (14)
+#define UART1_RSTN_BIT (15)
+#define SADC_RSTN_BIT (16)
+#define ADAPT_RSTN_BIT (17)
+#define TMR_RSTN_BIT (18)
+#define UART2_RSTN_BIT (19)
+#define SPI2_RSTN_BIT (20)
+#define JPG_ADAPT_RSTN_BIT (21)
+#define ARC_RSTN_BIT (22)
+#define EFUSE_RSTN_BIT (23)
+#define JPG_RSTN_BIT (24)
+#define VEU_RSTN_BIT (25)
+#define VPU_RSTN_BIT (26)
+#define ISP_RSTN_BIT (27)
+#define BGM_RSTN_BIT (28)
+#define I2C2_RSTN_BIT (29)
+#define EPHY_RSTN_BIT (30)
+#define SYS_RSTN_BIT (31)
+
+/* SWRST_AHB_CTRL */
+#define EMC_HRSTN_BIT (0)
+#define SDC1_HRSTN_BIT (1)
+#define SDC0_HRSTN_BIT (2)
+#define AES_HRSTN_BIT (3)
+#define DMAC0_HRSTN_BIT (4)
+#define INTC_HRSTN_BIT (5)
+#define JPEG_ADAPT_HRSTN_BIT (7)
+#define JPEG_HRSTN_BIT (8)
+#define VCU_HRSTN_BIT (9)
+#define VPU_HRSTN_BIT (10)
+#define ISP_HRSTN_BIT (11)
+#define USB_HRSTN_BIT (12)
+#define HRSTN_BIT (13)
+#define EMAC_HRSTN_BIT (17)
+#define DDRC_HRSTN_BIT (19)
+#define DMAC1_HRSTN_BIT (20)
+#define BGM_HRSTN_BIT (22)
+#define ADAPT_HRSTN_BIT (23)
+
+
+/* SWRST_APB_CTRL */
+#define ACODEC_PRSTN_BIT (0)
+#define I2S_PRSTN_BIT (1)
+#define UART1_PRSTN_BIT (2)
+#define UART0_PRSTN_BIT (3)
+#define SPI0_PRSTN_BIT (4)
+#define SPI1_PRSTN_BIT (5)
+#define GPIO0_PRSTN_BIT (6)
+#define UART2_PRSTN_BIT (7)
+#define I2C2_PRSTN_BIT (8)
+#define I2C0_PRSTN_BIT (9)
+#define I2C1_PRSTN_BIT (10)
+#define TMR_PRSTN_BIT (11)
+#define PWM_PRSTN_BIT (12)
+#define MIPIW_PRSTN_BIT (13)
+#define MIPIC_PRSTN_BIT (14)
+#define RTC_PRSTN_BIT (15)
+#define SADC_PRSTN_BIT (16)
+#define EFUSE_PRSTN_BIT (17)
+#define SPI2_PRSTN_BIT (18)
+#define WDT_PRSTN_BIT (19)
+#define GPIO1_PRSTN_BIT (20)
+
+/* timer clk fpga 1M,soc 50M*/
+#ifdef CONFIG_FPGA
+#define TIMER_CLK (1000000)
+#else
+#define TIMER_CLK (50000000)
+#endif
+
+#define UART1_TX_HW_HANDSHAKE (9)
+#define UART1_RX_HW_HANDSHAKE (8)
+#define UART2_TX_HW_HANDSHAKE (13)
+#define UART2_RX_HW_HANDSHAKE (12)
+#define UART1_DMA_TX_CHAN (4)
+#define UART1_DMA_RX_CHAN (5)
+#define UART2_DMA_TX_CHAN (4)
+#define UART2_DMA_RX_CHAN (5)
+
+/*sdio*/
+#define SIMPLE_0 (0)
+#define SIMPLE_22 (1)
+#define SIMPLE_45 (2)
+#define SIMPLE_67 (3)
+#define SIMPLE_90 (4)
+#define SIMPLE_112 (5)
+#define SIMPLE_135 (6)
+#define SIMPLE_157 (7)
+#define SIMPLE_180 (8)
+#define SIMPLE_202 (9)
+#define SIMPLE_225 (10)
+#define SIMPLE_247 (11)
+#define SIMPLE_270 (12)
+#define SIMPLE_292 (13)
+#define SIMPLE_315 (14)
+#define SIMPLE_337 (15)
+
+
+
+#define SDIO0_RST_BIT (~UL(1<<2))
+#define SDIO0_CLK_RATE (50000000)
+#define SDIO0_CLK_DRV_SHIFT (20)
+#define SDIO0_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO0_CLK_SAM_SHIFT (16)
+#define SDIO0_CLK_SAM_DEGREE (SIMPLE_0)
+
+
+#define SDIO1_RST_BIT (~UL(1<<1))
+#define SDIO1_CLK_RATE (50000000)
+#define SDIO1_CLK_DRV_SHIFT (12)
+#define SDIO1_CLK_DRV_DEGREE (SIMPLE_180)
+#define SDIO1_CLK_SAM_SHIFT (8)
+#define SDIO1_CLK_SAM_DEGREE (SIMPLE_0)
+
+#define SDC0_HRSTN (0x1<<2)
+#define SDC1_HRSTN (0x1<<1)
+#define SDC2_HRSTN (0)
+
+
+/*usb*/
+#define IRQ_UHOST USBC_IRQ
+#define FH_PA_OTG USBC_REG_BASE
+#define IRQ_OTG IRQ_UHOST
+#define FH_SZ_USBHOST SZ_1M
+#define FH_SZ_OTG SZ_1M
+
+#define USB_UTMI_RST_BIT (0x1<<1)
+#define USB_PHY_RST_BIT (0x11)
+#define USB_SLEEP_MODE_BIT (0x1<<24)
+#define USB_IDDQ_PWR_BIT (0x1<<10)
+
+
+/* Specific Uart Number */
+#define FH_UART_NUMBER 3
+#define CLK_SCAN_BIT_POS (28)
+#define INSIDE_PHY_ENABLE_BIT_POS (24)
+#define MAC_REF_CLK_DIV_MASK (0x0f)
+#define MAC_REF_CLK_DIV_BIT_POS (24)
+#define MAC_PAD_RMII_CLK_MASK (0x0f)
+#define MAC_PAD_RMII_CLK_BIT_POS (24)
+#define MAC_PAD_MAC_REF_CLK_BIT_POS (28)
+#define ETH_REF_CLK_OUT_GATE_BIT_POS (25)
+#define ETH_RMII_CLK_OUT_GATE_BIT_POS (28)
+#define IN_OR_OUT_PHY_SEL_BIT_POS (26)
+#define INSIDE_CLK_GATE_BIT_POS (0)
+#define INSIDE_PHY_SHUTDOWN_BIT_POS (31)
+#define INSIDE_PHY_RST_BIT_POS (30)
+#define INSIDE_PHY_TRAINING_BIT_POS (27)
+#define INSIDE_PHY_TRAINING_MASK (0x0f)
+
+#define TRAINING_EFUSE_ACTIVE_BIT_POS 4
+
+#endif /* __ASM_ARCH_HL_H */
diff --git a/arch/arm/mach-fh/fh8858v210/iopad.h b/arch/arm/mach-fh/fh8858v210/iopad.h
new file mode 100644
index 00000000..be10c032
--- /dev/null
+++ b/arch/arm/mach-fh/fh8858v210/iopad.h
@@ -0,0 +1,729 @@
+#include <mach/pinctrl.h>
+#include <mach/pinctrl_osdep.h>
+#include <mach/board_config.h>
+
+/* PINCTRL_FUNC */
+PINCTRL_FUNC(GPIO30, 0, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO31, 1, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 1, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO32, 2, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 2, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 2, FUNC2, PUPD_UP, 0);
+PINCTRL_FUNC(UART0_TX, 3, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO33, 3, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART0_RX, 4, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO34, 4, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C0_SCL, 5, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO35, 5, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(I2C0_SDA, 6, FUNC0, PUPD_UP, 0);
+PINCTRL_FUNC(GPIO36, 6, FUNC1, PUPD_UP, 0);
+PINCTRL_FUNC(SENSOR_CLK, 7, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO12, 7, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO13, 8, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 9, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO39, 9, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 9, FUNC3, PUPD_NONE, 3);
+PINCTRL_FUNC(TEST_O_INT_RMII_CLK, 9, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 10, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO40, 10, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 10, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_0, 10, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 11, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO37, 11, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 11, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 11, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 11, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXD_1, 11, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 12, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO38, 12, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 12, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 12, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 12, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_INT_RMII_TXEN, 12, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 13, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO41, 13, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM4, 13, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 13, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 13, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_0, 13, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 14, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO42, 14, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM5, 14, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 14, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 14, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_RXD_1, 14, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 15, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO47, 15, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 15, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_CRSDV, 15, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM0, 16, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO43, 16, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SCL, 16, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 16, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_0, 16, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM1, 17, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO44, 17, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C2_SDA, 17, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 17, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXD_1, 17, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM2, 18, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO45, 18, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM3, 19, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO46, 19, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RMII_CLK, 20, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO48, 20, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 20, FUNC2, PUPD_NONE, 3);
+PINCTRL_FUNC(PWM2, 20, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_REF_CLK, 21, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(MAC_TXD_0, 22, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO49, 22, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 22, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM3, 22, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXD_1, 23, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO50, 23, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 23, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM4, 23, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_TXEN, 24, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO51, 24, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 24, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM5, 24, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_0, 25, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO52, 25, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 25, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM6, 25, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXD_1, 26, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO53, 26, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 26, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM7, 26, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_RXDV, 27, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO54, 27, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 27, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(PWM8, 27, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 28, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO55, 28, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 28, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 29, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO56, 29, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CLK, 30, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO57, 30, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SCL, 30, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 31, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO58, 31, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(I2C1_SDA, 31, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CMD_RSP, 32, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO59, 32, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_TX, 32, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_0, 33, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO60, 33, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART1_RX, 33, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_1, 34, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO61, 34, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_TX, 34, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_2, 35, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO62, 35, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(UART2_RX, 35, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_DATA_3, 36, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO63, 36, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TRSTN, 37, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO0, 37, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DO, 37, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DO, 37, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CLK, 37, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CLK, 37, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADDAT, 37, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM6, 37, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDC, 37, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDO, 38, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO1, 38, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_DI, 38, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_DI, 38, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_CSN_0, 38, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_CSN_0, 38, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DADAT, 38, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM7, 38, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_I, 38, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TDI, 39, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO2, 39, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_CLK, 39, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_CLK, 39, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_TXD, 39, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_TXD, 39, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADBCLK, 39, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM8, 39, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_O, 39, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TCK, 40, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO3, 40, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_I2S_WS, 40, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(DW_I2S_WS, 40, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI1_RXD, 40, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI2_RXD, 40, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_ADLRC, 40, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM9, 40, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDIO_I, 40, FUNC8, PUPD_NONE, 0);
+PINCTRL_FUNC(ARM_JTAG_TMS, 41, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO4, 41, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(AC_MCLK, 41, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_PWREN, 41, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 41, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_I_INT_SMI_MDC, 41, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI0_CLK, 42, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO5, 42, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CLK, 42, FUNC4, PUPD_NONE, 3);
+PINCTRL_FUNC(SSI0_CSN_0, 43, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO6, 43, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_CMD_RSP, 43, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_TXD, 44, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO7, 44, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_0, 44, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_RXD, 45, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO8, 45, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_1, 45, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D2, 46, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO9, 46, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_TX, 46, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SCL, 46, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_2, 46, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI0_D3, 47, FUNC0, PUPD_NONE, 4);
+PINCTRL_FUNC(GPIO10, 47, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART1_RX, 47, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C1_SDA, 47, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(SD1_DATA_3, 47, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 48, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO11, 48, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CLK, 48, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 49, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO14, 49, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_CSN_0, 49, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 50, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO15, 50, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_TXD, 50, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 51, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO16, 51, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SSI2_RXD, 51, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CD, 52, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO17, 52, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(ARC_JTAG_TRSTN, 52, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(PAE_JTAG_TRSTN, 52, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD0_CLK, 53, FUNC0, PUPD_NONE, 3);
+PINCTRL_FUNC(GPIO18, 53, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CLK, 53, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDO, 53, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDO, 53, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_CMD_RSP, 54, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO19, 54, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_TXD, 54, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TDI, 54, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TDI, 54, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_0, 55, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO20, 55, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_RXD, 55, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TCK, 55, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TCK, 55, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_1, 56, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO21, 56, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 56, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(ARC_JTAG_TMS, 56, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(PAE_JTAG_TMS, 56, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_2, 57, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO22, 57, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_TX, 57, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SCL, 57, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DABCLK, 57, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SD0_DATA_3, 58, FUNC0, PUPD_NONE, 2);
+PINCTRL_FUNC(GPIO23, 58, FUNC1, PUPD_NONE, 2);
+PINCTRL_FUNC(SSI1_CSN_0, 58, FUNC2, PUPD_NONE, 2);
+PINCTRL_FUNC(UART2_RX, 58, FUNC3, PUPD_NONE, 2);
+PINCTRL_FUNC(I2C2_SDA, 58, FUNC4, PUPD_NONE, 2);
+PINCTRL_FUNC(ACIP_DALRC, 58, FUNC6, PUPD_NONE, 2);
+PINCTRL_FUNC(SADC_XAIN0, 59, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO26, 59, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN1, 60, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO27, 60, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN2, 61, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO24, 61, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(SADC_XAIN3, 62, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO25, 62, FUNC1, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO28, 63, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_ACT, 63, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM10, 63, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(USB_DBG_CLK, 63, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(SD1_CD, 63, FUNC5, PUPD_NONE, 2);
+PINCTRL_FUNC(TEST_O_INT_RMII_TXEN, 63, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDC, 63, FUNC7, PUPD_NONE, 0);
+PINCTRL_FUNC(GPIO29, 64, FUNC0, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_STA, 64, FUNC2, PUPD_NONE, 0);
+PINCTRL_FUNC(PWM11, 64, FUNC3, PUPD_NONE, 0);
+PINCTRL_FUNC(RTC_CLK, 64, FUNC4, PUPD_NONE, 0);
+PINCTRL_FUNC(ETH_LINK_SPD, 64, FUNC5, PUPD_NONE, 0);
+PINCTRL_FUNC(TEST_O_INT_SMI_MDIO_OE, 64, FUNC6, PUPD_NONE, 0);
+PINCTRL_FUNC(MAC_MDIO, 64, FUNC7, PUPD_NONE, 0);
+
+
+/* PINCTRL_MUX */
+
+PINCTRL_MUX(AC_I2S_CLK, 0, &PAD39_AC_I2S_CLK);
+PINCTRL_MUX(AC_I2S_DI, 0, &PAD38_AC_I2S_DI);
+PINCTRL_MUX(AC_I2S_DO, 0, &PAD37_AC_I2S_DO);
+PINCTRL_MUX(AC_I2S_WS, 0, &PAD40_AC_I2S_WS);
+PINCTRL_MUX(AC_MCLK, 0, &PAD41_AC_MCLK);
+
+PINCTRL_MUX(ARC_JTAG_TCK, 0, &PAD55_ARC_JTAG_TCK);
+PINCTRL_MUX(ARC_JTAG_TDI, 0, &PAD54_ARC_JTAG_TDI);
+PINCTRL_MUX(ARC_JTAG_TDO, 0, &PAD53_ARC_JTAG_TDO);
+PINCTRL_MUX(ARC_JTAG_TMS, 0, &PAD56_ARC_JTAG_TMS);
+PINCTRL_MUX(ARC_JTAG_TRSTN, 0, &PAD52_ARC_JTAG_TRSTN);
+
+PINCTRL_MUX(ARM_JTAG_TCK, 0, &PAD40_ARM_JTAG_TCK);
+PINCTRL_MUX(ARM_JTAG_TDI, 0, &PAD39_ARM_JTAG_TDI);
+PINCTRL_MUX(ARM_JTAG_TDO, 0, &PAD38_ARM_JTAG_TDO);
+PINCTRL_MUX(ARM_JTAG_TMS, 0, &PAD41_ARM_JTAG_TMS);
+PINCTRL_MUX(ARM_JTAG_TRSTN, 0, &PAD37_ARM_JTAG_TRSTN);
+
+PINCTRL_MUX(DW_I2S_CLK, 0, &PAD39_DW_I2S_CLK);
+PINCTRL_MUX(DW_I2S_DI, 0, &PAD38_DW_I2S_DI);
+PINCTRL_MUX(DW_I2S_DO, 0, &PAD37_DW_I2S_DO);
+PINCTRL_MUX(DW_I2S_WS, 0, &PAD40_DW_I2S_WS);
+
+PINCTRL_MUX(ETH_LINK_ACT, 1, &PAD1_ETH_LINK_ACT,
+ &PAD63_ETH_LINK_ACT);
+PINCTRL_MUX(ETH_LINK_SPD, 1, &PAD2_ETH_LINK_SPD,
+ &PAD64_ETH_LINK_SPD);
+PINCTRL_MUX(ETH_LINK_STA, 1, &PAD2_ETH_LINK_STA,
+ &PAD64_ETH_LINK_STA);
+
+PINCTRL_MUX(I2C0_SCL, 0, &PAD5_I2C0_SCL);
+PINCTRL_MUX(I2C0_SDA, 0, &PAD6_I2C0_SDA);
+
+PINCTRL_MUX(I2C1_SCL, 2, &PAD11_I2C1_SCL, &PAD30_I2C1_SCL, &PAD46_I2C1_SCL);
+PINCTRL_MUX(I2C1_SDA, 2, &PAD12_I2C1_SDA, &PAD31_I2C1_SDA, &PAD47_I2C1_SDA);
+
+PINCTRL_MUX(I2C2_SCL, 1, &PAD16_I2C2_SCL, &PAD57_I2C2_SCL);
+PINCTRL_MUX(I2C2_SDA, 1, &PAD17_I2C2_SDA, &PAD58_I2C2_SDA);
+
+PINCTRL_MUX(MAC_MDC, 0, &PAD28_MAC_MDC, &PAD63_MAC_MDC);
+PINCTRL_MUX(MAC_MDIO, 0, &PAD29_MAC_MDIO, &PAD64_MAC_MDIO);
+PINCTRL_MUX(MAC_REF_CLK, 0, &PAD21_MAC_REF_CLK);
+PINCTRL_MUX(MAC_RMII_CLK, 0, &PAD20_MAC_RMII_CLK);
+PINCTRL_MUX(MAC_RXDV, 0, &PAD27_MAC_RXDV);
+PINCTRL_MUX(MAC_RXD_0, 0, &PAD25_MAC_RXD_0);
+PINCTRL_MUX(MAC_RXD_1, 0, &PAD26_MAC_RXD_1);
+PINCTRL_MUX(MAC_TXD_0, 0, &PAD22_MAC_TXD_0);
+PINCTRL_MUX(MAC_TXD_1, 0, &PAD23_MAC_TXD_1);
+PINCTRL_MUX(MAC_TXEN, 0, &PAD24_MAC_TXEN);
+
+PINCTRL_MUX(PAE_JTAG_TCK, 0, &PAD55_PAE_JTAG_TCK);
+PINCTRL_MUX(PAE_JTAG_TDI, 0, &PAD54_PAE_JTAG_TDI);
+PINCTRL_MUX(PAE_JTAG_TDO, 0, &PAD53_PAE_JTAG_TDO);
+PINCTRL_MUX(PAE_JTAG_TMS, 0, &PAD56_PAE_JTAG_TMS);
+PINCTRL_MUX(PAE_JTAG_TRSTN, 0, &PAD52_PAE_JTAG_TRSTN);
+
+PINCTRL_MUX(PWM0, 0, &PAD16_PWM0);
+PINCTRL_MUX(PWM1, 0, &PAD17_PWM1);
+PINCTRL_MUX(PWM10, 0, &PAD63_PWM10);
+PINCTRL_MUX(PWM11, 0, &PAD64_PWM11);
+PINCTRL_MUX(PWM2, 0, &PAD11_PWM2, &PAD18_PWM2, &PAD20_PWM2);
+PINCTRL_MUX(PWM3, 0, &PAD12_PWM3, &PAD19_PWM3, &PAD22_PWM3);
+PINCTRL_MUX(PWM4, 0, &PAD13_PWM4, &PAD23_PWM4);
+PINCTRL_MUX(PWM5, 0, &PAD14_PWM5, &PAD24_PWM5);
+PINCTRL_MUX(PWM6, 1, &PAD25_PWM6, &PAD37_PWM6);
+PINCTRL_MUX(PWM7, 1, &PAD26_PWM7, &PAD38_PWM7);
+PINCTRL_MUX(PWM8, 1, &PAD27_PWM8, &PAD39_PWM8);
+PINCTRL_MUX(PWM9, 1, &PAD28_PWM9, &PAD40_PWM9);
+
+PINCTRL_MUX(RTC_CLK, 0, &PAD64_RTC_CLK);
+
+PINCTRL_MUX(SADC_XAIN0, 0, &PAD59_SADC_XAIN0);
+PINCTRL_MUX(SADC_XAIN1, 0, &PAD60_SADC_XAIN1);
+PINCTRL_MUX(SADC_XAIN2, 0, &PAD61_SADC_XAIN2);
+PINCTRL_MUX(SADC_XAIN3, 0, &PAD62_SADC_XAIN3);
+
+PINCTRL_MUX(SD0_CD, 0, &PAD52_SD0_CD);
+PINCTRL_MUX(SD0_CLK, 0, &PAD53_SD0_CLK);
+PINCTRL_MUX(SD0_CMD_RSP, 0, &PAD54_SD0_CMD_RSP);
+PINCTRL_MUX(SD0_DATA_0, 0, &PAD55_SD0_DATA_0);
+PINCTRL_MUX(SD0_DATA_1, 0, &PAD56_SD0_DATA_1);
+PINCTRL_MUX(SD0_DATA_2, 0, &PAD57_SD0_DATA_2);
+PINCTRL_MUX(SD0_DATA_3, 0, &PAD58_SD0_DATA_3);
+
+PINCTRL_MUX(SD1_CD, 2, &PAD10_SD1_CD, &PAD22_SD1_CD, &PAD31_SD1_CD,
+ &PAD41_SD1_CD, &PAD63_SD1_CD);
+PINCTRL_MUX(SD1_CLK, 2, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP, 2, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0, 2, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1, 2, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2, 2, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3, 2, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+PINCTRL_MUX(SENSOR_CLK, 0, &PAD7_SENSOR_CLK);
+
+PINCTRL_MUX(SSI0_CLK, 0, &PAD42_SSI0_CLK);
+PINCTRL_MUX(SSI0_D2, 0, &PAD46_SSI0_D2);
+PINCTRL_MUX(SSI0_D3, 0, &PAD47_SSI0_D3);
+PINCTRL_MUX(SSI0_RXD, 0, &PAD45_SSI0_RXD);
+PINCTRL_MUX(SSI0_TXD, 0, &PAD44_SSI0_TXD);
+
+PINCTRL_MUX(SSI1_CLK, 2, &PAD11_SSI1_CLK, &PAD37_SSI1_CLK, &PAD48_SSI1_CLK,
+ &PAD53_SSI1_CLK);
+PINCTRL_MUX(SSI1_RXD, 2, &PAD14_SSI1_RXD, &PAD40_SSI1_RXD, &PAD51_SSI1_RXD,
+ &PAD55_SSI1_RXD);
+PINCTRL_MUX(SSI1_TXD, 2, &PAD13_SSI1_TXD, &PAD39_SSI1_TXD, &PAD50_SSI1_TXD,
+ &PAD54_SSI1_TXD);
+
+PINCTRL_MUX(SSI2_CLK, 1, &PAD37_SSI2_CLK, &PAD48_SSI2_CLK);
+PINCTRL_MUX(SSI2_CSN_0, 1, &PAD38_SSI2_CSN_0, &PAD49_SSI2_CSN_0);
+PINCTRL_MUX(SSI2_RXD, 1, &PAD40_SSI2_RXD, &PAD51_SSI2_RXD);
+PINCTRL_MUX(SSI2_TXD, 1, &PAD39_SSI2_TXD, &PAD50_SSI2_TXD);
+
+PINCTRL_MUX(UART0_RX, 0, &PAD4_UART0_RX);
+PINCTRL_MUX(UART0_TX, 0, &PAD3_UART0_TX);
+
+PINCTRL_MUX(UART1_RX, 0, &PAD10_UART1_RX, &PAD33_UART1_RX, &PAD47_UART1_RX);
+PINCTRL_MUX(UART1_TX, 0, &PAD9_UART1_TX, &PAD32_UART1_TX, &PAD46_UART1_TX);
+
+PINCTRL_MUX(UART2_RX, 0, &PAD14_UART2_RX, &PAD17_UART2_RX, &PAD35_UART2_RX,
+ &PAD58_UART2_RX);
+PINCTRL_MUX(UART2_TX, 0, &PAD13_UART2_TX, &PAD16_UART2_TX, &PAD34_UART2_TX,
+ &PAD57_UART2_TX);
+
+PINCTRL_MUX(USB_PWREN, 0, &PAD15_USB_PWREN, &PAD41_USB_PWREN);
+
+PINCTRL_MUX(GPIO0, 0, &PAD37_GPIO0);
+PINCTRL_MUX(GPIO1, 0, &PAD38_GPIO1);
+PINCTRL_MUX(GPIO2, 0, &PAD39_GPIO2);
+PINCTRL_MUX(GPIO3, 0, &PAD40_GPIO3);
+PINCTRL_MUX(GPIO4, 0, &PAD41_GPIO4);
+PINCTRL_MUX(GPIO5, 0, &PAD42_GPIO5);
+PINCTRL_MUX(GPIO6, 0, &PAD43_GPIO6);
+PINCTRL_MUX(GPIO7, 0, &PAD44_GPIO7);
+PINCTRL_MUX(GPIO8, 0, &PAD45_GPIO8);
+PINCTRL_MUX(GPIO9, 0, &PAD46_GPIO9);
+PINCTRL_MUX(GPIO10, 0, &PAD47_GPIO10);
+PINCTRL_MUX(GPIO11, 0, &PAD48_GPIO11);
+PINCTRL_MUX(GPIO12, 0, &PAD7_GPIO12);
+PINCTRL_MUX(GPIO13, 0, &PAD8_GPIO13);
+PINCTRL_MUX(GPIO14, 0, &PAD49_GPIO14);
+PINCTRL_MUX(GPIO15, 0, &PAD50_GPIO15);
+PINCTRL_MUX(GPIO16, 0, &PAD51_GPIO16);
+PINCTRL_MUX(GPIO17, 0, &PAD52_GPIO17);
+PINCTRL_MUX(GPIO18, 0, &PAD53_GPIO18);
+PINCTRL_MUX(GPIO19, 0, &PAD54_GPIO19);
+PINCTRL_MUX(GPIO20, 0, &PAD55_GPIO20);
+PINCTRL_MUX(GPIO21, 0, &PAD56_GPIO21);
+PINCTRL_MUX(GPIO22, 0, &PAD57_GPIO22);
+PINCTRL_MUX(GPIO23, 0, &PAD58_GPIO23);
+PINCTRL_MUX(GPIO24, 0, &PAD61_GPIO24);
+PINCTRL_MUX(GPIO25, 0, &PAD62_GPIO25);
+PINCTRL_MUX(GPIO26, 0, &PAD59_GPIO26);
+PINCTRL_MUX(GPIO27, 0, &PAD60_GPIO27);
+PINCTRL_MUX(GPIO28, 0, &PAD63_GPIO28);
+PINCTRL_MUX(GPIO29, 0, &PAD64_GPIO29);
+PINCTRL_MUX(GPIO30, 0, &PAD0_GPIO30);
+PINCTRL_MUX(GPIO31, 0, &PAD1_GPIO31);
+PINCTRL_MUX(GPIO32, 0, &PAD2_GPIO32);
+PINCTRL_MUX(GPIO33, 0, &PAD3_GPIO33);
+PINCTRL_MUX(GPIO34, 0, &PAD4_GPIO34);
+PINCTRL_MUX(GPIO35, 0, &PAD5_GPIO35);
+PINCTRL_MUX(GPIO36, 0, &PAD6_GPIO36);
+PINCTRL_MUX(GPIO37, 0, &PAD11_GPIO37);
+PINCTRL_MUX(GPIO38, 0, &PAD12_GPIO38);
+PINCTRL_MUX(GPIO39, 0, &PAD9_GPIO39);
+PINCTRL_MUX(GPIO40, 0, &PAD10_GPIO40);
+PINCTRL_MUX(GPIO41, 0, &PAD13_GPIO41);
+PINCTRL_MUX(GPIO42, 0, &PAD14_GPIO42);
+PINCTRL_MUX(GPIO43, 0, &PAD16_GPIO43);
+PINCTRL_MUX(GPIO44, 0, &PAD17_GPIO44);
+PINCTRL_MUX(GPIO45, 0, &PAD18_GPIO45);
+PINCTRL_MUX(GPIO46, 0, &PAD19_GPIO46);
+PINCTRL_MUX(GPIO47, 0, &PAD15_GPIO47);
+PINCTRL_MUX(GPIO48, 0, &PAD20_GPIO48);
+PINCTRL_MUX(GPIO49, 0, &PAD22_GPIO49);
+PINCTRL_MUX(GPIO50, 0, &PAD23_GPIO50);
+PINCTRL_MUX(GPIO51, 0, &PAD24_GPIO51);
+PINCTRL_MUX(GPIO52, 0, &PAD25_GPIO52);
+PINCTRL_MUX(GPIO53, 0, &PAD26_GPIO53);
+PINCTRL_MUX(GPIO54, 0, &PAD27_GPIO54);
+PINCTRL_MUX(GPIO55, 0, &PAD28_GPIO55);
+PINCTRL_MUX(GPIO56, 0, &PAD29_GPIO56);
+PINCTRL_MUX(GPIO57, 0, &PAD30_GPIO57);
+PINCTRL_MUX(GPIO58, 0, &PAD31_GPIO58);
+PINCTRL_MUX(GPIO59, 0, &PAD32_GPIO59);
+PINCTRL_MUX(GPIO60, 0, &PAD33_GPIO60);
+PINCTRL_MUX(GPIO61, 0, &PAD34_GPIO61);
+PINCTRL_MUX(GPIO62, 0, &PAD35_GPIO62);
+PINCTRL_MUX(GPIO63, 0, &PAD36_GPIO63);
+
+PINCTRL_MUX(SD1_CLK_EMMC, 3, &PAD9_SD1_CLK, &PAD20_SD1_CLK, &PAD30_SD1_CLK,
+ &PAD42_SD1_CLK);
+PINCTRL_MUX(SD1_CMD_RSP_EMMC, 3, &PAD11_SD1_CMD_RSP, &PAD23_SD1_CMD_RSP,
+ &PAD32_SD1_CMD_RSP, &PAD43_SD1_CMD_RSP);
+PINCTRL_MUX(SD1_DATA_0_EMMC, 3, &PAD12_SD1_DATA_0, &PAD24_SD1_DATA_0,
+ &PAD33_SD1_DATA_0, &PAD44_SD1_DATA_0);
+PINCTRL_MUX(SD1_DATA_1_EMMC, 3, &PAD13_SD1_DATA_1, &PAD25_SD1_DATA_1,
+ &PAD34_SD1_DATA_1, &PAD45_SD1_DATA_1);
+PINCTRL_MUX(SD1_DATA_2_EMMC, 3, &PAD14_SD1_DATA_2, &PAD26_SD1_DATA_2,
+ &PAD35_SD1_DATA_2, &PAD46_SD1_DATA_2);
+PINCTRL_MUX(SD1_DATA_3_EMMC, 3, &PAD15_SD1_DATA_3, &PAD27_SD1_DATA_3,
+ &PAD36_SD1_DATA_3, &PAD47_SD1_DATA_3);
+
+/* PINCTRL_DEVICE */
+PINCTRL_DEVICE(ACI2S, 5, &MUX_AC_I2S_CLK, &MUX_AC_I2S_DI, &MUX_AC_I2S_DO,
+ &MUX_AC_I2S_WS, &MUX_AC_MCLK);
+PINCTRL_DEVICE(AC_MCLK, 1, &MUX_AC_MCLK);
+PINCTRL_DEVICE(ARCJTAG, 5, &MUX_ARC_JTAG_TCK, &MUX_ARC_JTAG_TDI,
+ &MUX_ARC_JTAG_TDO, &MUX_ARC_JTAG_TMS, &MUX_ARC_JTAG_TRSTN);
+PINCTRL_DEVICE(ARMJTAG, 5, &MUX_ARM_JTAG_TCK, &MUX_ARM_JTAG_TDI,
+ &MUX_ARM_JTAG_TDO, &MUX_ARM_JTAG_TMS, &MUX_ARM_JTAG_TRSTN);
+PINCTRL_DEVICE(DWI2S, 4, &MUX_DW_I2S_CLK, &MUX_DW_I2S_DI, &MUX_DW_I2S_DO,
+ &MUX_DW_I2S_WS);
+PINCTRL_DEVICE(ETH, 2, &MUX_ETH_LINK_ACT, &MUX_ETH_LINK_STA);
+PINCTRL_DEVICE(I2C0, 2, &MUX_I2C0_SCL, &MUX_I2C0_SDA);
+PINCTRL_DEVICE(I2C1, 2, &MUX_I2C1_SCL, &MUX_I2C1_SDA);
+PINCTRL_DEVICE(I2C2, 2, &MUX_I2C2_SCL, &MUX_I2C2_SDA);
+PINCTRL_DEVICE(PAEJTAG, 5, &MUX_PAE_JTAG_TCK, &MUX_PAE_JTAG_TDI,
+ &MUX_PAE_JTAG_TDO, &MUX_PAE_JTAG_TMS, &MUX_PAE_JTAG_TRSTN);
+PINCTRL_DEVICE(PWM0, 1, &MUX_PWM0);
+PINCTRL_DEVICE(PWM1, 1, &MUX_PWM1);
+PINCTRL_DEVICE(PWM10, 1, &MUX_PWM10);
+PINCTRL_DEVICE(PWM11, 1, &MUX_PWM11);
+PINCTRL_DEVICE(PWM2, 1, &MUX_PWM2);
+PINCTRL_DEVICE(PWM3, 1, &MUX_PWM3);
+PINCTRL_DEVICE(PWM4, 1, &MUX_PWM4);
+PINCTRL_DEVICE(PWM5, 1, &MUX_PWM5);
+PINCTRL_DEVICE(PWM6, 1, &MUX_PWM6);
+PINCTRL_DEVICE(PWM7, 1, &MUX_PWM7);
+PINCTRL_DEVICE(PWM8, 1, &MUX_PWM8);
+PINCTRL_DEVICE(PWM9, 1, &MUX_PWM9);
+PINCTRL_DEVICE(RMII, 10, &MUX_MAC_MDC, &MUX_MAC_MDIO, &MUX_MAC_REF_CLK,
+ &MUX_MAC_RMII_CLK, &MUX_MAC_RXDV, &MUX_MAC_RXD_0, &MUX_MAC_RXD_1,
+ &MUX_MAC_TXD_0, &MUX_MAC_TXD_1, &MUX_MAC_TXEN);
+PINCTRL_DEVICE(RTC, 1, &MUX_RTC_CLK);
+PINCTRL_DEVICE(SADC_XAIN0, 1, &MUX_SADC_XAIN0);
+PINCTRL_DEVICE(SADC_XAIN1, 1, &MUX_SADC_XAIN1);
+PINCTRL_DEVICE(SADC_XAIN2, 1, &MUX_SADC_XAIN2);
+PINCTRL_DEVICE(SADC_XAIN3, 1, &MUX_SADC_XAIN3);
+PINCTRL_DEVICE(SD0, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_1BIT_NO_WP, 4, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0);
+PINCTRL_DEVICE(SD0_NO_WP, 7, &MUX_SD0_CD, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP,
+ &MUX_SD0_DATA_0, &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD0_WIFI, 6, &MUX_SD0_CLK, &MUX_SD0_CMD_RSP, &MUX_SD0_DATA_0,
+ &MUX_SD0_DATA_1, &MUX_SD0_DATA_2, &MUX_SD0_DATA_3);
+PINCTRL_DEVICE(SD1, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_1BIT_NO_WP, 4, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0);
+PINCTRL_DEVICE(SD1_NO_WP, 7, &MUX_SD1_CD, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP,
+ &MUX_SD1_DATA_0, &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SD1_WIFI, 6, &MUX_SD1_CLK, &MUX_SD1_CMD_RSP, &MUX_SD1_DATA_0,
+ &MUX_SD1_DATA_1, &MUX_SD1_DATA_2, &MUX_SD1_DATA_3);
+PINCTRL_DEVICE(SENSOR_CLK, 1, &MUX_SENSOR_CLK);
+PINCTRL_DEVICE(SSI0, 4, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_RXD,
+ &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI0_4BIT, 6, &MUX_GPIO6, &MUX_SSI0_CLK, &MUX_SSI0_D2,
+ &MUX_SSI0_D3, &MUX_SSI0_RXD, &MUX_SSI0_TXD);
+PINCTRL_DEVICE(SSI1, 4, &MUX_GPIO14, &MUX_SSI1_CLK, &MUX_SSI1_RXD,
+ &MUX_SSI1_TXD);
+PINCTRL_DEVICE(SSI2, 4, &MUX_SSI2_CLK, &MUX_SSI2_CSN_0, &MUX_SSI2_RXD,
+ &MUX_SSI2_TXD);
+PINCTRL_DEVICE(UART0, 2, &MUX_UART0_RX, &MUX_UART0_TX);
+PINCTRL_DEVICE(UART1, 2, &MUX_UART1_RX, &MUX_UART1_TX);
+PINCTRL_DEVICE(UART2, 2, &MUX_UART2_RX, &MUX_UART2_TX);
+PINCTRL_DEVICE(USB, 1, &MUX_USB_PWREN);
+PINCTRL_DEVICE(GPIO0, 1, &MUX_GPIO0);
+PINCTRL_DEVICE(GPIO1, 1, &MUX_GPIO1);
+PINCTRL_DEVICE(GPIO2, 1, &MUX_GPIO2);
+PINCTRL_DEVICE(GPIO3, 1, &MUX_GPIO3);
+PINCTRL_DEVICE(GPIO4, 1, &MUX_GPIO4);
+PINCTRL_DEVICE(GPIO5, 1, &MUX_GPIO5);
+PINCTRL_DEVICE(GPIO6, 1, &MUX_GPIO6);
+PINCTRL_DEVICE(GPIO7, 1, &MUX_GPIO7);
+PINCTRL_DEVICE(GPIO8, 1, &MUX_GPIO8);
+PINCTRL_DEVICE(GPIO9, 1, &MUX_GPIO9);
+PINCTRL_DEVICE(GPIO10, 1, &MUX_GPIO10);
+PINCTRL_DEVICE(GPIO11, 1, &MUX_GPIO11);
+PINCTRL_DEVICE(GPIO12, 1, &MUX_GPIO12);
+PINCTRL_DEVICE(GPIO13, 1, &MUX_GPIO13);
+PINCTRL_DEVICE(GPIO14, 1, &MUX_GPIO14);
+PINCTRL_DEVICE(GPIO15, 1, &MUX_GPIO15);
+PINCTRL_DEVICE(GPIO16, 1, &MUX_GPIO16);
+PINCTRL_DEVICE(GPIO17, 1, &MUX_GPIO17);
+PINCTRL_DEVICE(GPIO18, 1, &MUX_GPIO18);
+PINCTRL_DEVICE(GPIO19, 1, &MUX_GPIO19);
+PINCTRL_DEVICE(GPIO20, 1, &MUX_GPIO20);
+PINCTRL_DEVICE(GPIO21, 1, &MUX_GPIO21);
+PINCTRL_DEVICE(GPIO22, 1, &MUX_GPIO22);
+PINCTRL_DEVICE(GPIO23, 1, &MUX_GPIO23);
+PINCTRL_DEVICE(GPIO24, 1, &MUX_GPIO24);
+PINCTRL_DEVICE(GPIO25, 1, &MUX_GPIO25);
+PINCTRL_DEVICE(GPIO26, 1, &MUX_GPIO26);
+PINCTRL_DEVICE(GPIO27, 1, &MUX_GPIO27);
+PINCTRL_DEVICE(GPIO28, 1, &MUX_GPIO28);
+PINCTRL_DEVICE(GPIO29, 1, &MUX_GPIO29);
+PINCTRL_DEVICE(GPIO30, 1, &MUX_GPIO30);
+PINCTRL_DEVICE(GPIO31, 1, &MUX_GPIO31);
+PINCTRL_DEVICE(GPIO32, 1, &MUX_GPIO32);
+PINCTRL_DEVICE(GPIO33, 1, &MUX_GPIO33);
+PINCTRL_DEVICE(GPIO34, 1, &MUX_GPIO34);
+PINCTRL_DEVICE(GPIO35, 1, &MUX_GPIO35);
+PINCTRL_DEVICE(GPIO36, 1, &MUX_GPIO36);
+PINCTRL_DEVICE(GPIO37, 1, &MUX_GPIO37);
+PINCTRL_DEVICE(GPIO38, 1, &MUX_GPIO38);
+PINCTRL_DEVICE(GPIO39, 1, &MUX_GPIO39);
+PINCTRL_DEVICE(GPIO40, 1, &MUX_GPIO40);
+PINCTRL_DEVICE(GPIO41, 1, &MUX_GPIO41);
+PINCTRL_DEVICE(GPIO42, 1, &MUX_GPIO42);
+PINCTRL_DEVICE(GPIO43, 1, &MUX_GPIO43);
+PINCTRL_DEVICE(GPIO44, 1, &MUX_GPIO44);
+PINCTRL_DEVICE(GPIO45, 1, &MUX_GPIO45);
+PINCTRL_DEVICE(GPIO46, 1, &MUX_GPIO46);
+PINCTRL_DEVICE(GPIO47, 1, &MUX_GPIO47);
+PINCTRL_DEVICE(GPIO48, 1, &MUX_GPIO48);
+PINCTRL_DEVICE(GPIO49, 1, &MUX_GPIO49);
+PINCTRL_DEVICE(GPIO50, 1, &MUX_GPIO50);
+PINCTRL_DEVICE(GPIO51, 1, &MUX_GPIO51);
+PINCTRL_DEVICE(GPIO52, 1, &MUX_GPIO52);
+PINCTRL_DEVICE(GPIO53, 1, &MUX_GPIO53);
+PINCTRL_DEVICE(GPIO54, 1, &MUX_GPIO54);
+PINCTRL_DEVICE(GPIO55, 1, &MUX_GPIO55);
+PINCTRL_DEVICE(GPIO56, 1, &MUX_GPIO56);
+PINCTRL_DEVICE(GPIO57, 1, &MUX_GPIO57);
+PINCTRL_DEVICE(GPIO58, 1, &MUX_GPIO58);
+PINCTRL_DEVICE(GPIO59, 1, &MUX_GPIO59);
+PINCTRL_DEVICE(GPIO60, 1, &MUX_GPIO60);
+PINCTRL_DEVICE(GPIO61, 1, &MUX_GPIO61);
+PINCTRL_DEVICE(GPIO62, 1, &MUX_GPIO62);
+PINCTRL_DEVICE(GPIO63, 1, &MUX_GPIO63);
+
+PINCTRL_DEVICE(SD1_EMMC, 6, &MUX_SD1_CLK_EMMC, &MUX_SD1_CMD_RSP_EMMC,
+ &MUX_SD1_DATA_0_EMMC, &MUX_SD1_DATA_1_EMMC, &MUX_SD1_DATA_2_EMMC,
+ &MUX_SD1_DATA_3_EMMC);
+
+void fh_pinctrl_init_devicelist(OS_LIST *list)
+{
+ OS_LIST_EMPTY(list);
+
+ /*PINCTRL_ADD_DEVICE*/
+ PINCTRL_ADD_DEVICE(ACI2S);
+ PINCTRL_ADD_DEVICE(AC_MCLK);
+ PINCTRL_ADD_DEVICE(ARCJTAG);
+ PINCTRL_ADD_DEVICE(ARMJTAG);
+ PINCTRL_ADD_DEVICE(DWI2S);
+ PINCTRL_ADD_DEVICE(ETH);
+ PINCTRL_ADD_DEVICE(I2C0);
+ PINCTRL_ADD_DEVICE(I2C1);
+ PINCTRL_ADD_DEVICE(I2C2);
+ PINCTRL_ADD_DEVICE(PAEJTAG);
+ PINCTRL_ADD_DEVICE(PWM0);
+ PINCTRL_ADD_DEVICE(PWM1);
+ PINCTRL_ADD_DEVICE(PWM10);
+ PINCTRL_ADD_DEVICE(PWM11);
+ PINCTRL_ADD_DEVICE(PWM2);
+ PINCTRL_ADD_DEVICE(PWM3);
+ PINCTRL_ADD_DEVICE(PWM4);
+ PINCTRL_ADD_DEVICE(PWM5);
+ PINCTRL_ADD_DEVICE(PWM6);
+ PINCTRL_ADD_DEVICE(PWM7);
+ PINCTRL_ADD_DEVICE(PWM8);
+ PINCTRL_ADD_DEVICE(PWM9);
+ PINCTRL_ADD_DEVICE(RMII);
+ PINCTRL_ADD_DEVICE(RTC);
+ PINCTRL_ADD_DEVICE(SADC_XAIN0);
+ PINCTRL_ADD_DEVICE(SADC_XAIN1);
+ PINCTRL_ADD_DEVICE(SADC_XAIN2);
+ PINCTRL_ADD_DEVICE(SADC_XAIN3);
+ PINCTRL_ADD_DEVICE(SD0);
+ PINCTRL_ADD_DEVICE(SD0_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_NO_WP);
+ PINCTRL_ADD_DEVICE(SD0_WIFI);
+ PINCTRL_ADD_DEVICE(SD1);
+ PINCTRL_ADD_DEVICE(SD1_1BIT_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_NO_WP);
+ PINCTRL_ADD_DEVICE(SD1_WIFI);
+ PINCTRL_ADD_DEVICE(SENSOR_CLK);
+ PINCTRL_ADD_DEVICE(SSI0);
+ PINCTRL_ADD_DEVICE(SSI0_4BIT);
+ PINCTRL_ADD_DEVICE(SSI1);
+ PINCTRL_ADD_DEVICE(SSI2);
+ PINCTRL_ADD_DEVICE(UART0);
+ PINCTRL_ADD_DEVICE(UART1);
+ PINCTRL_ADD_DEVICE(UART2);
+ PINCTRL_ADD_DEVICE(USB);
+ PINCTRL_ADD_DEVICE(GPIO0);
+ PINCTRL_ADD_DEVICE(GPIO1);
+ PINCTRL_ADD_DEVICE(GPIO2);
+ PINCTRL_ADD_DEVICE(GPIO3);
+ PINCTRL_ADD_DEVICE(GPIO4);
+ PINCTRL_ADD_DEVICE(GPIO5);
+ PINCTRL_ADD_DEVICE(GPIO6);
+ PINCTRL_ADD_DEVICE(GPIO7);
+ PINCTRL_ADD_DEVICE(GPIO8);
+ PINCTRL_ADD_DEVICE(GPIO9);
+ PINCTRL_ADD_DEVICE(GPIO10);
+ PINCTRL_ADD_DEVICE(GPIO11);
+ PINCTRL_ADD_DEVICE(GPIO12);
+ PINCTRL_ADD_DEVICE(GPIO13);
+ PINCTRL_ADD_DEVICE(GPIO14);
+ PINCTRL_ADD_DEVICE(GPIO15);
+ PINCTRL_ADD_DEVICE(GPIO16);
+ PINCTRL_ADD_DEVICE(GPIO17);
+ PINCTRL_ADD_DEVICE(GPIO18);
+ PINCTRL_ADD_DEVICE(GPIO19);
+ PINCTRL_ADD_DEVICE(GPIO20);
+ PINCTRL_ADD_DEVICE(GPIO21);
+ PINCTRL_ADD_DEVICE(GPIO22);
+ PINCTRL_ADD_DEVICE(GPIO23);
+ PINCTRL_ADD_DEVICE(GPIO24);
+ PINCTRL_ADD_DEVICE(GPIO25);
+ PINCTRL_ADD_DEVICE(GPIO26);
+ PINCTRL_ADD_DEVICE(GPIO27);
+ PINCTRL_ADD_DEVICE(GPIO28);
+ PINCTRL_ADD_DEVICE(GPIO29);
+ PINCTRL_ADD_DEVICE(GPIO30);
+ PINCTRL_ADD_DEVICE(GPIO31);
+ PINCTRL_ADD_DEVICE(GPIO32);
+ PINCTRL_ADD_DEVICE(GPIO33);
+ PINCTRL_ADD_DEVICE(GPIO34);
+ PINCTRL_ADD_DEVICE(GPIO35);
+ PINCTRL_ADD_DEVICE(GPIO36);
+ PINCTRL_ADD_DEVICE(GPIO37);
+ PINCTRL_ADD_DEVICE(GPIO38);
+ PINCTRL_ADD_DEVICE(GPIO39);
+ PINCTRL_ADD_DEVICE(GPIO40);
+ PINCTRL_ADD_DEVICE(GPIO41);
+ PINCTRL_ADD_DEVICE(GPIO42);
+ PINCTRL_ADD_DEVICE(GPIO43);
+ PINCTRL_ADD_DEVICE(GPIO44);
+ PINCTRL_ADD_DEVICE(GPIO45);
+ PINCTRL_ADD_DEVICE(GPIO46);
+ PINCTRL_ADD_DEVICE(GPIO47);
+ PINCTRL_ADD_DEVICE(GPIO48);
+ PINCTRL_ADD_DEVICE(GPIO49);
+ PINCTRL_ADD_DEVICE(GPIO50);
+ PINCTRL_ADD_DEVICE(GPIO51);
+ PINCTRL_ADD_DEVICE(GPIO52);
+ PINCTRL_ADD_DEVICE(GPIO53);
+ PINCTRL_ADD_DEVICE(GPIO54);
+ PINCTRL_ADD_DEVICE(GPIO55);
+ PINCTRL_ADD_DEVICE(GPIO56);
+ PINCTRL_ADD_DEVICE(GPIO57);
+ PINCTRL_ADD_DEVICE(GPIO58);
+ PINCTRL_ADD_DEVICE(GPIO59);
+ PINCTRL_ADD_DEVICE(GPIO60);
+ PINCTRL_ADD_DEVICE(GPIO61);
+ PINCTRL_ADD_DEVICE(GPIO62);
+ PINCTRL_ADD_DEVICE(GPIO63);
+
+ PINCTRL_ADD_DEVICE(SD1_EMMC);
+}
+
+char *fh_pinctrl_selected_devices[] =
+{
+ CONFIG_PINCTRL_SELECT
+};
diff --git a/arch/arm/mach-fh/fh_chipid.c b/arch/arm/mach-fh/fh_chipid.c
new file mode 100644
index 00000000..6a5b8446
--- /dev/null
+++ b/arch/arm/mach-fh/fh_chipid.c
@@ -0,0 +1,214 @@
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <mach/pmu.h>
+#include <mach/fh_chipid.h>
+#include "soc.h"
+
+#define CHIP_INFO(__plat_id, __chip_id, __chip_mask, chip, size) \
+ { \
+ ._plat_id = __plat_id, \
+ ._chip_id = __chip_id, \
+ ._chip_mask = __chip_mask, \
+ .chip_id = FH_CHIP_##chip, \
+ .ddr_size = size, \
+ .chip_name = #chip, \
+ },
+
+#define RD_REG 0xffffffff
+
+static struct fh_chip_info chip_infos[] = {
+ CHIP_INFO(0x46488302, 0x37, 0x3F, FH8632, 512)
+ CHIP_INFO(0x46488302, 0x07, 0x3F, FH8632v2, 512)
+ CHIP_INFO(0x17092901, 0xC, 0xF, FH8852, 512)
+ CHIP_INFO(0x17092901, 0xD, 0xF, FH8856, 1024)
+ CHIP_INFO(0x18112301, 0x0, 0x0, FH8626V100, 512)
+ CHIP_INFO(0x19112201, 0x00000001, 0x00FFFFFF, FH8852V200, RD_REG)
+ CHIP_INFO(0x19112201, 0x00100001, 0x00FFFFFF, FH8856V200, RD_REG)
+ CHIP_INFO(0x19112201, 0x00410001, 0x00FFFFFF, FH8858V200, RD_REG)
+ CHIP_INFO(0x19112201, 0x00200001, 0x00FFFFFF, FH8856V201, RD_REG)
+ CHIP_INFO(0x19112201, 0x00300001, 0x00FFFFFF, FH8858V201, RD_REG)
+ CHIP_INFO(0x19112201, 0x00000002, 0x00FFFFFF, FH8852V210, RD_REG)
+ CHIP_INFO(0x19112201, 0x00100002, 0x00FFFFFF, FH8856V210, RD_REG)
+ CHIP_INFO(0x19112201, 0x00410002, 0x00FFFFFF, FH8858V210, RD_REG)
+ CHIP_INFO(0x20031601, 0xc, 0xc, FH8652, RD_REG)
+ CHIP_INFO(0x20031601, 0x8, 0xc, FH8656, RD_REG)
+ CHIP_INFO(0x20031601, 0x4, 0xc, FH8658, RD_REG)
+};
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+
+#define FH_GET_CHIP_ID(plat_id, chip_id) \
+ int plat_id = 0;\
+ int chip_id = 0;\
+ fh_get_chipid(&plat_id, &chip_id)
+
+
+struct fh_chip_info *fh_get_chip_info(void)
+{
+ static struct fh_chip_info *chip_info = NULL;
+ struct fh_chip_info *info = NULL;
+ int plat_id = 0;
+ int chip_id = 0;
+ int i = 0;
+
+ if (chip_info != NULL)
+ return chip_info;
+
+ fh_get_chipid(&plat_id, &chip_id);
+#ifdef REG_PMU_CHIP_INFO
+ chip_id = fh_pmu_get_reg(REG_PMU_CHIP_INFO);
+#endif
+ for (i = 0; i < ARRAY_SIZE(chip_infos); i++)
+ {
+ info = &chip_infos[i];
+ if (plat_id == info->_plat_id && (chip_id & info->_chip_mask) == info->_chip_id)
+ {
+ chip_info = info;
+ if (chip_info->ddr_size == RD_REG)
+ chip_info->ddr_size = fh_pmu_get_ddrsize();
+ return info;
+ }
+ }
+ pr_err("Error: unknown chip\n");
+ return NULL;
+}
+EXPORT_SYMBOL(fh_get_chip_info);
+
+unsigned int fh_get_ddrsize_mbit(void)
+{
+ struct fh_chip_info *info = fh_get_chip_info();
+
+ if (info)
+ return info->ddr_size;
+ return 0;
+}
+EXPORT_SYMBOL(fh_get_ddrsize_mbit);
+
+char *fh_get_chipname(void)
+{
+ struct fh_chip_info *info = fh_get_chip_info();
+
+ if (info)
+ return info->chip_name;
+ return "UNKNOWN";
+}
+EXPORT_SYMBOL(fh_get_chipname);
+
+#define DEFINE_FUNC_FH_IS(name, chip) \
+unsigned int fh_is_##name(void) \
+{ \
+ struct fh_chip_info *info = fh_get_chip_info(); \
+ \
+ if (info) \
+ return info->chip_id == FH_CHIP_##chip; \
+ return 0; \
+} \
+EXPORT_SYMBOL(fh_is_##name)
+
+unsigned int fh_is_8632(void)
+{
+ struct fh_chip_info *info = fh_get_chip_info();
+
+ if (info)
+ return (info->chip_id == FH_CHIP_FH8632 || \
+ info->chip_id == FH_CHIP_FH8632v2);
+ return 0;
+}
+EXPORT_SYMBOL(fh_is_8632);
+
+DEFINE_FUNC_FH_IS(8830, FH8830);
+DEFINE_FUNC_FH_IS(8852, FH8852);
+DEFINE_FUNC_FH_IS(8856, FH8856);
+DEFINE_FUNC_FH_IS(8626v100, FH8626V100);
+DEFINE_FUNC_FH_IS(8852v200, FH8852V200);
+DEFINE_FUNC_FH_IS(8856v200, FH8856V200);
+DEFINE_FUNC_FH_IS(8858v200, FH8858V200);
+DEFINE_FUNC_FH_IS(8856v201, FH8856V201);
+DEFINE_FUNC_FH_IS(8858v201, FH8858V201);
+DEFINE_FUNC_FH_IS(8852v210, FH8852V210);
+DEFINE_FUNC_FH_IS(8856v210, FH8856V210);
+DEFINE_FUNC_FH_IS(8858v210, FH8858V210);
+DEFINE_FUNC_FH_IS(8652, FH8652);
+DEFINE_FUNC_FH_IS(8656, FH8656);
+DEFINE_FUNC_FH_IS(8658, FH8658);
+
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ unsigned int plat_id = 0;
+ unsigned int chip_id = 0;
+ fh_get_chipid(&plat_id, &chip_id);
+
+ seq_printf(sfile, "chip_name\t: %s\n", fh_get_chipname());
+ seq_printf(sfile, "ddr_size\t: %dMbit\n", fh_get_ddrsize_mbit());
+ seq_printf(sfile, "plat_id\t\t: 0x%x\npkg_id\t\t: 0x%x\n",
+ plat_id, chip_id);
+ return 0;
+}
+
+static const struct seq_operations chipid_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_chipid_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &chipid_seq_ops);
+}
+
+static const struct file_operations fh_chipid_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_chipid_proc_open,
+ .read = seq_read,
+};
+
+#define FH_CHIPID_PROC_FILE "driver/chip"
+static struct proc_dir_entry *chipid_proc_file;
+
+int fh_chipid_init(void)
+{
+ chipid_proc_file = proc_create(FH_CHIPID_PROC_FILE, 0644, NULL,
+ &fh_chipid_proc_ops);
+
+ if (!chipid_proc_file) {
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, "CHIP ID");
+ return -EINVAL;
+ }
+
+ pr_info("CHIP: %s\n", fh_get_chipname());
+
+ return 0;
+}
+
diff --git a/arch/arm/mach-fh/fh_common.c b/arch/arm/mach-fh/fh_common.c
new file mode 100644
index 00000000..1037c3a2
--- /dev/null
+++ b/arch/arm/mach-fh/fh_common.c
@@ -0,0 +1,110 @@
+/*
+ * fh_common.c
+ *
+ * Copyright (C) 2019 Fullhan Microelectronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <mach/fh_common.h>
+
+/**
+ * fh_setscheduler - change the scheduling policy and/or RT priority of `current` thread.
+ * @policy: new policy. egz. SCHED_RR
+ * @priority: new priority. egz MAX_USER_RT_PRIO-12
+ * @param: structure containing the new RT priority.
+ *
+ * NOTE that the task may be already dead.
+ */
+void fh_setscheduler(int policy, int priority)
+{
+ struct sched_param param;
+ param.sched_priority = priority;
+ sched_setscheduler(current, policy, &param);
+}
+EXPORT_SYMBOL(fh_setscheduler);
+
+int fh_clk_enable(struct clk *clk)
+{
+ return clk_enable(clk);
+}
+EXPORT_SYMBOL(fh_clk_enable);
+
+unsigned long fh_clk_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk);
+}
+EXPORT_SYMBOL(fh_clk_get_rate);
+
+int fh_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ return clk_set_rate(clk, rate);
+}
+EXPORT_SYMBOL(fh_clk_set_rate);
+
+int fh_clk_prepare(struct clk *clk)
+{
+ return clk_prepare(clk);
+}
+EXPORT_SYMBOL(fh_clk_prepare);
+
+void fh_clk_disable(struct clk *clk)
+{
+ clk_disable(clk);
+}
+EXPORT_SYMBOL(fh_clk_disable);
+
+void fh_clk_unprepare(struct clk *clk)
+{
+ clk_unprepare(clk);
+}
+EXPORT_SYMBOL(fh_clk_unprepare);
+
+int fh_clk_prepare_enable(struct clk *clk)
+{
+ return clk_prepare_enable(clk);
+}
+EXPORT_SYMBOL(fh_clk_prepare_enable);
+
+void fh_clk_disable_unprepare(struct clk *clk)
+{
+ clk_disable_unprepare(clk);
+}
+EXPORT_SYMBOL(fh_clk_disable_unprepare);
+
+bool fh_clk_is_enabled(struct clk *clk)
+{
+ return __clk_is_enabled(clk);
+}
+EXPORT_SYMBOL(fh_clk_is_enabled);
+
+
+int fh_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ return clk_set_parent(clk, parent);
+}
+EXPORT_SYMBOL(fh_clk_set_parent);
+
+struct clk *fh_clk_get_parent(struct clk *clk)
+{
+ return clk_get_parent(clk);
+}
+EXPORT_SYMBOL(fh_clk_get_parent);
+
+bool fh_clk_has_parent(struct clk *clk, struct clk *parent)
+{
+ return clk_has_parent(clk, parent);
+}
+EXPORT_SYMBOL(fh_clk_has_parent);
+
+unsigned int fh_irq_create_mapping(struct irq_domain *domain,
+ irq_hw_number_t hwirq)
+{
+ return irq_create_mapping(domain, hwirq);
+}
+EXPORT_SYMBOL(fh_irq_create_mapping);
diff --git a/arch/arm/mach-fh/fullhan.c b/arch/arm/mach-fh/fullhan.c
new file mode 100644
index 00000000..4b62405d
--- /dev/null
+++ b/arch/arm/mach-fh/fullhan.c
@@ -0,0 +1,121 @@
+/*
+ * Fullhan FH8810 board support
+ *
+ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/fh_chipid.h>
+#include <mach/pmu.h>
+
+#ifdef CONFIG_CPU_V6
+#include <asm/system_misc.h>
+static void fh_cpu_do_idle(void)
+{
+}
+
+static int __init fh_cpu_idle_init(void)
+{
+ arm_pm_idle = fh_cpu_do_idle;
+ return 0;
+}
+early_initcall(fh_cpu_idle_init);
+#endif
+
+
+static int __init fullhan_init_early(void)
+{
+
+ fh_pmu_init();
+ fh_chipid_init();
+
+#ifdef CONFIG_EMULATION
+ pr_info("---Emulation Version---\n");
+#endif
+ return 0;
+}
+arch_initcall(fullhan_init_early);
+
+#ifdef CONFIG_USE_OF
+
+static const char *fh8856v200_compat[] __initconst = {
+ "fh,fh8856v200",
+ NULL,
+};
+
+static const char *fh8858v200_compat[] __initconst = {
+ "fh,fh8858v200",
+ NULL,
+};
+
+static const char *fh8852v200_compat[] __initconst = {
+ "fh,fh8852v200",
+ NULL,
+};
+
+static const char *fh8856v210_compat[] __initconst = {
+ "fh,fh8856v210",
+ NULL,
+};
+
+static const char *fh8858v210_compat[] __initconst = {
+ "fh,fh8858v210",
+ NULL,
+};
+
+static const char *fh8852v210_compat[] __initconst = {
+ "fh,fh8852v210",
+ NULL,
+};
+
+
+
+
+
+
+
+DT_MACHINE_START(FH8856V200, "Fullhan FH8856V200 (Flattened Device Tree)")
+ .dt_compat = fh8856v200_compat,
+MACHINE_END
+
+DT_MACHINE_START(FH8858V200, "Fullhan FH8858V200 (Flattened Device Tree)")
+ .dt_compat = fh8858v200_compat,
+MACHINE_END
+
+DT_MACHINE_START(FH8852V200, "Fullhan FH8852V200 (Flattened Device Tree)")
+ .dt_compat = fh8852v200_compat,
+MACHINE_END
+
+
+DT_MACHINE_START(FH8856V210, "Fullhan FH8856V210 (Flattened Device Tree)")
+ .dt_compat = fh8856v210_compat,
+MACHINE_END
+
+DT_MACHINE_START(FH8858V210, "Fullhan FH8858V210 (Flattened Device Tree)")
+ .dt_compat = fh8858v210_compat,
+MACHINE_END
+
+DT_MACHINE_START(FH8852V210, "Fullhan FH8852V210 (Flattened Device Tree)")
+ .dt_compat = fh8852v210_compat,
+MACHINE_END
+
+
+
+
+
+
+
+#endif
diff --git a/arch/arm/mach-fh/hotplug.c b/arch/arm/mach-fh/hotplug.c
new file mode 100644
index 00000000..6b25b845
--- /dev/null
+++ b/arch/arm/mach-fh/hotplug.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/system_misc.h>
+#include "core.h"
+
+/* Sysctrl registers in Hi3620 SoC */
+#define SCISOEN 0xc0
+#define SCISODIS 0xc4
+#define SCPERPWREN 0xd0
+#define SCPERPWRDIS 0xd4
+#define SCCPUCOREEN 0xf4
+#define SCCPUCOREDIS 0xf8
+#define SCPERCTRL0 0x200
+#define SCCPURSTEN 0x410
+#define SCCPURSTDIS 0x414
+
+/*
+ * bit definition in SCISOEN/SCPERPWREN/...
+ *
+ * CPU2_ISO_CTRL (1 << 5)
+ * CPU3_ISO_CTRL (1 << 6)
+ * ...
+ */
+#define CPU2_ISO_CTRL (1 << 5)
+
+/*
+ * bit definition in SCPERCTRL0
+ *
+ * CPU0_WFI_MASK_CFG (1 << 28)
+ * CPU1_WFI_MASK_CFG (1 << 29)
+ * ...
+ */
+#define CPU0_WFI_MASK_CFG (1 << 28)
+
+/*
+ * bit definition in SCCPURSTEN/...
+ *
+ * CPU0_SRST_REQ_EN (1 << 0)
+ * CPU1_SRST_REQ_EN (1 << 1)
+ * ...
+ */
+#define CPU0_HPM_SRST_REQ_EN (1 << 22)
+#define CPU0_DBG_SRST_REQ_EN (1 << 12)
+#define CPU0_NEON_SRST_REQ_EN (1 << 4)
+#define CPU0_SRST_REQ_EN (1 << 0)
+
+#define HIX5HD2_PERI_CRG20 0x50
+#define CRG20_CPU1_RESET (1 << 17)
+
+#define HIX5HD2_PERI_PMC0 0x1000
+#define PMC0_CPU1_WAIT_MTCOMS_ACK (1 << 8)
+#define PMC0_CPU1_PMC_ENABLE (1 << 7)
+#define PMC0_CPU1_POWERDOWN (1 << 3)
+
+#define HIP01_PERI9 0x50
+#define PERI9_CPU1_RESET (1 << 1)
+
+
+static void __iomem *ctrl_base;
+
+
+static int fhca7_hotplug_init(void)
+{
+ struct device_node *node;
+
+ node = of_find_compatible_node(NULL, NULL, "fh,fh-pmu");
+ if (!node) {
+ return -ENOENT;
+ }
+
+ ctrl_base = of_iomap(node, 0);
+ of_node_put(node);
+ if (!ctrl_base) {
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void fhca7_set_cpu(int cpu, bool enable)
+{
+ if (!ctrl_base) {
+ if (fhca7_hotplug_init() < 0)
+ return;
+ }
+
+}
+
+static inline void cpu_enter_lowpower(void)
+{
+ unsigned int v;
+
+ flush_cache_all();
+
+ /*
+ * Turn off coherency and L1 D-cache
+ */
+ asm volatile(
+ " mrc p15, 0, %0, c1, c0, 1\n"
+ " bic %0, %0, #0x40\n"
+ " mcr p15, 0, %0, c1, c0, 1\n"
+ " mrc p15, 0, %0, c1, c0, 0\n"
+ " bic %0, %0, #0x04\n"
+ " mcr p15, 0, %0, c1, c0, 0\n"
+ : "=&r" (v)
+ : "r" (0)
+ : "cc");
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void fhca7_cpu_die(unsigned int cpu)
+{
+ cpu_enter_lowpower();
+ arch_cpu_idle();
+
+ /* We should have never returned from idle */
+ panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+}
+
+int fhca7_cpu_kill(unsigned int cpu)
+{
+ fhca7_set_cpu(cpu, false);
+
+ return 1;
+}
+#endif
diff --git a/arch/arm/mach-fh/include/mach/board_config.h b/arch/arm/mach-fh/include/mach/board_config.h
new file mode 100644
index 00000000..3d1b0551
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/board_config.h
@@ -0,0 +1,44 @@
+#ifndef BOARD_CONFIG_H_
+#define BOARD_CONFIG_H_
+
+/*
+ * GPIO0 -> IRCUT_ON
+ * GPIO1 -> IRCUT_OFF
+ * GPIO2 -> USB_PWREN
+ * GPIO11 -> EMAC PHY Reset
+ * GPIO12 -> CIS_CLK
+ * GPIO13 -> CIS_RSTN
+ * GPIO14 -> CIS_PDN
+ * GPIO19 -> SD1_PWREN/WIFI_REG_ON
+ * GPIO20 -> AK7755 Reset
+ * GPIO24 -> LED0
+ * GPIO25 -> LED1
+ * GPIO26 -> Reset Configs
+ * GPIO27 -> AK7755 PowerDown
+ * GPIO28 -> IR
+ * GPIO53 -> USB_PWREN/SD0_PWREN
+ * GPIO55 -> SD1 WIFI Interrupt
+ */
+
+#define CONFIG_SD_CD_FIXED
+
+#define CONFIG_ISP_CLK_RATE 200000000
+#define CONFIG_JPEG_CLK_RATE 200000000
+#define CONFIG_VEU_CLK_RATE 300000000
+
+#define USB_VBUS_PWR_GPIO (47)
+#define ETH_GPIO "ETH", "GPIO48", "GPIO49", "GPIO50", "GPIO51", "GPIO52",\
+ "GPIO53", "GPIO54", "GPIO55", "GPIO56"
+
+#define CONFIG_PINCTRL_SELECT \
+ "I2C0", "PWM2", "PWM3", "PWM4", "PWM5", "PWM6", "PWM7", \
+ "PWM8", "PWM9", "SADC_XAIN0", "SADC_XAIN1", \
+ "SADC_XAIN2", "SADC_XAIN3", "SD0_NO_WP", "SD1_NO_WP", \
+ "SENSOR_CLK", "SSI0_4BIT", "UART0", "UART1", "GPIO4", \
+ "GPIO13", "GPIO14", "GPIO15", ETH_GPIO, \
+ "GPIO30", "GPIO31", "GPIO32", "GPIO43", "GPIO44", \
+ "GPIO47", \
+\
+ "GPIO11", "GPIO16", "GPIO45", "GPIO46"
+
+#endif /* BOARD_CONFIG_H_ */
diff --git a/arch/arm/mach-fh/include/mach/clock.h b/arch/arm/mach-fh/include/mach/clock.h
new file mode 100644
index 00000000..b761ab44
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/clock.h
@@ -0,0 +1,59 @@
+#ifndef __FH_CLOCK_H__
+#define __FH_CLOCK_H__
+
+#include <linux/list.h>
+#include <linux/clkdev.h>
+
+#define CLOCK_MAX_PARENT 4
+
+#define OSC_FREQUENCY (24000000)
+
+#define CLOCK_FIXED (1<<0)
+#define CLOCK_NOGATE (1<<1)
+#define CLOCK_NODIV (1<<2)
+#define CLOCK_NORESET (1<<3)
+#define CLOCK_MULTI_PARENT (1<<4)
+#define CLOCK_PLL (1<<5)
+#define CLOCK_PLL_P (1<<6)
+#define CLOCK_PLL_R (1<<7)
+#define CLOCK_HIDE (1<<8)
+#define CLOCK_CIS (1<<9)
+#define CLOCK_PHASE (1<<10)
+
+
+#define CLK(dev, con, ck) \
+ { \
+ .dev_id = dev, \
+ .con_id = con, \
+ .clk = ck, \
+ }
+
+struct clk_usr {
+ char *name;
+ unsigned long frequency;
+};
+
+
+struct fh_clk {
+ const char *name;
+ unsigned long frequency;
+ unsigned int flag;
+ int select;
+ struct fh_clk *parent[CLOCK_MAX_PARENT];
+ int prediv;
+ int divide;
+ unsigned int div_reg_offset;
+ unsigned int div_reg_mask;
+ unsigned int en_reg_offset;
+ unsigned int en_reg_mask;
+ unsigned int rst_reg_offset;
+ unsigned int rst_reg_mask;
+ unsigned int sel_reg_offset;
+ unsigned int sel_reg_mask;
+ unsigned int def_rate;
+};
+
+extern struct fh_clk *fh_clks[];
+extern int __init fh_clk_init(void);
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_chipid.h b/arch/arm/mach-fh/include/mach/fh_chipid.h
new file mode 100644
index 00000000..6c13d9d6
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_chipid.h
@@ -0,0 +1,57 @@
+#ifndef __FH_CHIPID_H__
+#define __FH_CHIPID_H__
+
+#define FH_CHIP_FH8830 0x883000A1
+#define FH_CHIP_FH8630M 0x883000B1
+#define FH_CHIP_FH8632 0x863200A1
+#define FH_CHIP_FH8632v2 0x863200A2
+#define FH_CHIP_FH8856 0x885600A1
+#define FH_CHIP_FH8852 0x885600B1
+#define FH_CHIP_FH8626V100 0x8626A100
+#define FH_CHIP_FH8852V200 0x8852A200
+#define FH_CHIP_FH8856V200 0x8856A200
+#define FH_CHIP_FH8858V200 0x8858A200
+#define FH_CHIP_FH8856V201 0x8856A201
+#define FH_CHIP_FH8858V201 0x8858A201
+#define FH_CHIP_FH8852V210 0x8852A210
+#define FH_CHIP_FH8856V210 0x8856A210
+#define FH_CHIP_FH8858V210 0x8858A210
+#define FH_CHIP_FH8652 0x8652A100
+#define FH_CHIP_FH8656 0x8656A100
+#define FH_CHIP_FH8658 0x8658A100
+
+struct fh_chip_info
+{
+ int _plat_id; /* 芯片寄存器中的plat_id */
+ int _chip_id; /* 芯片寄存器中的chip_id */
+ int _chip_mask; /* 芯片寄存器中的chip_id */
+ int chip_id; /* 芯片chip_id详见上述定义 */
+ int ddr_size; /* 芯片DDR大小单位Mbit */
+ char chip_name[32]; /* 芯片名称 */
+};
+
+void fh_get_chipid(unsigned int *plat_id, unsigned int *chip_id);
+unsigned int fh_get_ddrsize_mbit(void);
+char *fh_get_chipname(void);
+struct fh_chip_info *fh_get_chip_info(void);
+
+unsigned int fh_is_8830(void);
+unsigned int fh_is_8632(void);
+unsigned int fh_is_8852(void);
+unsigned int fh_is_8856(void);
+unsigned int fh_is_8626v100(void);
+unsigned int fh_is_8852v200(void);
+unsigned int fh_is_8856v200(void);
+unsigned int fh_is_8858v200(void);
+unsigned int fh_is_8856v201(void);
+unsigned int fh_is_8858v201(void);
+unsigned int fh_is_8852v210(void);
+unsigned int fh_is_8856v210(void);
+unsigned int fh_is_8858v210(void);
+unsigned int fh_is_8652(void);
+unsigned int fh_is_8656(void);
+unsigned int fh_is_8658(void);
+
+int fh_chipid_init(void);
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_common.h b/arch/arm/mach-fh/include/mach/fh_common.h
new file mode 100644
index 00000000..4b5289f9
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_common.h
@@ -0,0 +1,27 @@
+#ifndef __FH_COMMON_H__
+#define __FH_COMMON_H__
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/irqdomain.h>
+
+/*change the scheduling policy and/or RT priority of `current` thread. */
+void fh_setscheduler(int policy, int priority);
+
+int fh_clk_enable(struct clk *clk);
+unsigned long fh_clk_get_rate(struct clk *clk);
+int fh_clk_set_rate(struct clk *clk, unsigned long rate);
+int fh_clk_prepare(struct clk *clk);
+void fh_clk_disable(struct clk *clk);
+void fh_clk_unprepare(struct clk *clk);
+int fh_clk_prepare_enable(struct clk *clk);
+void fh_clk_disable_unprepare(struct clk *clk);
+int fh_clk_set_parent(struct clk *clk, struct clk *parent);
+struct clk *fh_clk_get_parent(struct clk *clk);
+bool fh_clk_has_parent(struct clk *clk, struct clk *parent);
+
+unsigned int fh_irq_create_mapping(struct irq_domain *domain,
+ irq_hw_number_t hwirq);
+bool fh_clk_is_enabled(struct clk *clk);
+
+#endif
\ No newline at end of file
diff --git a/arch/arm/mach-fh/include/mach/fh_dma_plat.h b/arch/arm/mach-fh/include/mach/fh_dma_plat.h
new file mode 100644
index 00000000..989a7e7b
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_dma_plat.h
@@ -0,0 +1,94 @@
+#ifndef __FH_DMAC_PLAT_H__
+#define __FH_DMAC_PLAT_H__
+
+/****************************************************************************
+ * #include section
+ * add #include here if any
+ ***************************************************************************/
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/printk.h>
+/****************************************************************************
+ * #define section
+ * add constant #define here if any
+ ***************************************************************************/
+
+#define FH_AXI_DMA_PRINT(fmt, ...) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+
+#define SOC_CACHE_LINE_SIZE 32
+#define AXI_DMA_NULL (0)
+#define AXI_DMA_ASSERT(n) BUG_ON(!(n))
+
+#define axi_dma_lock_init(p, name) mutex_init(p)
+#define _axi_dma_lock(p, t) mutex_lock(p)
+#define axi_dma_unlock(p) mutex_unlock(p)
+#define axi_dma_trylock(p) mutex_trylock(p)
+#define axi_dma_memset(s, c, cnt) memset(s, c, cnt)
+#define axi_dma_malloc(s) kzalloc(s, GFP_KERNEL)
+#define axi_dma_free(s) kfree(s)
+#define axi_dma_min(d0,d1) min(d0, d1)
+#define AXI_DMA_TICK_PER_SEC 100
+
+
+/****************************************************************************
+ * ADT section
+ * add Abstract Data Type definition here
+ ***************************************************************************/
+typedef signed char FH_SINT8;
+typedef signed short FH_SINT16;
+typedef signed int FH_SINT32;
+typedef unsigned char FH_UINT8;
+typedef unsigned short FH_UINT16;
+typedef unsigned int FH_UINT32;
+typedef signed int FH_ERR;
+
+typedef struct mutex axi_dma_lock_t;
+typedef struct list_head axi_dma_list;
+
+#define axi_dma_list_init(n) INIT_LIST_HEAD(n)
+#define axi_dma_list_insert_before(to, new) list_add_tail(new, to)
+#define axi_dma_list_remove(n) list_del(n)
+#define axi_dma_scanf sprintf
+
+
+/**
+ * struct fh_dma_platform_data - Controller configuration parameters
+ * @nr_channels: Number of channels supported by hardware (max 8)
+ * @is_private: The device channels should be marked as private and not for
+ * by the general purpose DMA channel allocator.
+ * @chan_allocation_order: Allocate channels starting from 0 or 7
+ * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0.
+ * @block_size: Maximum block size supported by the controller
+ * @nr_masters: Number of AHB masters supported by the controller
+ * @data_width: Maximum data width supported by hardware per AHB master
+ * (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
+ * @sd: slave specific data. Used for configuring channels
+ * @sd_count: count of slave data structures passed.
+ */
+struct fh_dma_platform_data {
+ unsigned int nr_channels;
+ bool is_private;
+#define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */
+#define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */
+ unsigned char chan_allocation_order;
+#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */
+#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */
+ unsigned char chan_priority;
+ unsigned short block_size;
+ unsigned char nr_masters;
+ unsigned char data_width[4];
+ char *clk_name;
+};
+
+
+struct fh_axi_dma_platform_data {
+#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */
+#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */
+ unsigned char chan_priority;
+ char *clk_name;
+};
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_dmac_plat.h b/arch/arm/mach-fh/include/mach/fh_dmac_plat.h
new file mode 100644
index 00000000..581e06ba
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_dmac_plat.h
@@ -0,0 +1,44 @@
+/*
+ * Driver for the Synopsys DesignWare DMA Controller (aka DMACA on
+ * AVR32 systems.)
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ * Copyright (C) 2010-2011 ST Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef FH_DMAC_PLAT_H
+#define FH_DMAC_PLAT_H
+
+#include <linux/dmaengine.h>
+#ifdef CONFIG_FH_DMAC
+
+struct fh_dma_platform_data {
+ unsigned int nr_channels;
+ bool is_private;
+#define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */
+#define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */
+ unsigned char chan_allocation_order;
+#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */
+#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */
+ unsigned char chan_priority;
+ unsigned short block_size;
+ unsigned char nr_masters;
+ unsigned char data_width[4];
+ char *clk_name;
+};
+
+#else
+
+struct fh_axi_dma_platform_data {
+ //unsigned int nr_channels;
+#define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */
+#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */
+ unsigned char chan_priority;
+ char *clk_name;
+};
+
+#endif
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_efuse_plat.h b/arch/arm/mach-fh/include/mach/fh_efuse_plat.h
new file mode 100644
index 00000000..bf63f460
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_efuse_plat.h
@@ -0,0 +1,9 @@
+#ifndef __FH_EFUSE_PLAT_H__
+#define __FH_EFUSE_PLAT_H__
+
+struct fh_efuse_platform_data {
+ u32 efuse_support_flag;
+ void *optee_uuid;
+};
+
+#endif
\ No newline at end of file
diff --git a/arch/arm/mach-fh/include/mach/fh_gmac_plat.h b/arch/arm/mach-fh/include/mach/fh_gmac_plat.h
new file mode 100644
index 00000000..7526eac7
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_gmac_plat.h
@@ -0,0 +1,10 @@
+#ifndef __FH_GMAC_PLAT_H__
+#define __FH_GMAC_PLAT_H__
+
+struct fh_gmac_platform_data {
+ u32 phy_reset_pin;
+ u32 speed_switch_pmu_reg;
+ u32 speed_switch_bit_pos;
+ u32 speed_switch_100M_val;
+};
+#endif
\ No newline at end of file
diff --git a/arch/arm/mach-fh/include/mach/fh_gpio_plat.h b/arch/arm/mach-fh/include/mach/fh_gpio_plat.h
new file mode 100644
index 00000000..fe08911c
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_gpio_plat.h
@@ -0,0 +1,33 @@
+#ifndef __FH_GPIO_PLAT_H__
+#define __FH_GPIO_PLAT_H__
+
+#define GPIO_NAME "FH_GPIO"
+
+#include <asm-generic/gpio.h>
+
+enum trigger_type {
+ SOFTWARE,
+ HARDWARE,
+};
+
+struct gpio_irq_info {
+ int irq_gpio;
+ int irq_line;
+ int irq_type;
+ int irq_gpio_val;
+ int irq_gpio_mode;
+};
+
+struct fh_gpio_chip {
+ struct gpio_chip chip;
+ void __iomem *base;
+ struct irq_domain *irq_domain;
+ struct platform_device *pdev;
+ int irq;
+ spinlock_t lock;
+
+ enum trigger_type type;
+ u32 gpio_wakeups;
+ u32 gpio_backups;
+};
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_i2s_plat.h b/arch/arm/mach-fh/include/mach/fh_i2s_plat.h
new file mode 100644
index 00000000..5a530f07
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_i2s_plat.h
@@ -0,0 +1,16 @@
+#ifndef __FH_I2S_PLAT_H__
+#define __FH_I2S_PLAT_H__
+
+struct fh_i2s_platform_data {
+ int dma_capture_channel;
+ int dma_playback_channel;
+ int dma_master;
+ int dma_rx_hs_num;
+ int dma_tx_hs_num;
+ char *clk;
+ char *pclk;
+ char *acodec_pclk;
+ char *acodec_mclk;
+};
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_l2mem.h b/arch/arm/mach-fh/include/mach/fh_l2mem.h
new file mode 100644
index 00000000..f2888f23
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_l2mem.h
@@ -0,0 +1,17 @@
+#ifndef __MACH_L2MEM_H
+#define __MACH_L2MEM_H
+
+/*
+ * L2MEM allocations return a CPU virtual address, or NULL on error.
+ * If a DMA address is requested and the L2MEM supports DMA, its
+ * mapped address is also returned.
+ *
+ * Errors include L2MEM memory not being available, and requesting
+ * DMA mapped L2MEM on systems which don't allow that.
+ */
+
+extern void *l2mem_alloc(size_t len);
+extern void *l2mem_dma_alloc(size_t len, dma_addr_t *dma);
+extern void l2mem_free(void *addr, size_t len);
+
+#endif /* __MACH_SRAL2MEM*/
diff --git a/arch/arm/mach-fh/include/mach/fh_mci_plat.h b/arch/arm/mach-fh/include/mach/fh_mci_plat.h
new file mode 100644
index 00000000..910595fc
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_mci_plat.h
@@ -0,0 +1,79 @@
+#ifndef __FH_MCI_PLAT_H__
+#define __FH_MCI_PLAT_H__
+
+struct fhmci_des {
+ unsigned long idmac_des_ctrl;
+ unsigned long idmac_des_buf_size;
+ unsigned long idmac_des_buf_addr;
+ unsigned long idmac_des_next_addr;
+};
+
+struct fhmci_host {
+ struct mmc_host *mmc;
+ spinlock_t lock;
+ struct mmc_request *mrq;
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+ void __iomem *base;
+ unsigned int card_status;
+ struct scatterlist *dma_sg;
+ unsigned int dma_sg_num;
+ unsigned int dma_alloc_size;
+ unsigned int dma_dir;
+ dma_addr_t dma_paddr;
+ unsigned int *dma_vaddr;
+ struct timer_list timer;
+ unsigned int irq;
+ unsigned int irq_status;
+ unsigned int is_tuning;
+ wait_queue_head_t intr_wait;
+ unsigned long pending_events;
+ unsigned int id;
+ struct fh_mci_board *pdata;
+ int fifo_depth;
+ unsigned int bus_hz;
+ unsigned int (*get_cd)(struct fhmci_host *host);
+ unsigned int (*get_ro)(struct fhmci_host *host);
+#define FHMCI_PEND_DTO_b (0)
+#define FHMCI_PEND_DTO_m (1 << FHMCI_PEND_DTO_b)
+ char isr_name[10];
+};
+
+/* Board platform data */
+struct fh_mci_board {
+ unsigned int num_slots;
+
+ unsigned int quirks; /* Workaround / Quirk flags */
+ unsigned int bus_hz; /* Bus speed */
+
+ unsigned int caps; /* Capabilities */
+
+ /* delay in mS before detecting cards after interrupt */
+ unsigned int detect_delay_ms;
+
+ int (*init)(unsigned int slot_id, void *irq_handler_t, void *);
+ unsigned int (*get_ro)(struct fhmci_host *host);
+ unsigned int (*get_cd)(struct fhmci_host *host);
+ int (*get_ocr)(unsigned int slot_id);
+ int (*get_bus_wd)(unsigned int slot_id);
+ /*
+ * Enable power to selected slot and set voltage to desired level.
+ * Voltage levels are specified using MMC_VDD_xxx defines defined
+ * in linux/mmc/host.h file.
+ */
+ void (*setpower)(unsigned int slot_id, unsigned int volt);
+ void (*exit)(unsigned int slot_id);
+ void (*select_slot)(unsigned int slot_id);
+
+ struct dw_mci_dma_ops *dma_ops;
+ struct dma_pdata *data;
+ struct block_settings *blk_settings;
+ int fifo_depth;
+ int drv_degree;
+ int sam_degree;
+ /*if rescan_max_num = 0 scan all times*/
+ unsigned int rescan_max_num;
+};
+
+#endif
+
diff --git a/arch/arm/mach-fh/include/mach/fh_predefined.h b/arch/arm/mach-fh/include/mach/fh_predefined.h
new file mode 100644
index 00000000..2e29254a
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_predefined.h
@@ -0,0 +1,33 @@
+#ifndef FH_PREDEFINED_H_
+#define FH_PREDEFINED_H_
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+
+typedef char SINT8;
+typedef short SINT16;
+typedef int SINT32;
+typedef long long SINT64;
+#define FALSE (0)
+#define TRUE (!FALSE)
+#define reg_read(addr) (*((volatile UINT32 *)(addr)))
+#define reg_write(addr,value) (*(volatile UINT32 *)(addr)=(value))
+
+#define GET_REG(addr) reg_read(addr)
+#define SET_REG(addr,value) reg_write(addr,value)
+#define SET_REG_M(addr,value,mask) reg_write(addr,(reg_read(addr)&(~(mask)))|((value)&(mask)))
+#define SET_REG_B(addr,element,highbit,lowbit) SET_REG_M((addr),((element)<<(lowbit)),(((1<<((highbit)-(lowbit)+1))-1)<<(lowbit)))
+
+#define GET_REG8(addr) (*((volatile UINT8 *)(addr)))
+#define SET_REG8(addr,value) (*(volatile UINT8 *)(addr)=(value))
+
+#define LD8(addr) (*((volatile u8 *)(addr)))
+#define ST8(addr,value) (*(volatile u8 *)(addr)=(value))
+#define LD16(addr) (*((volatile u16 *)(addr)))
+#define ST16(addr,value) (*(volatile u16 *)(addr)=(value))
+#define LD32(addr) (*((volatile u32 *)(addr)))
+#define ST32(addr,value) (*(volatile u32 *)(addr)=(value))
+
+#endif /* FH_PREDEFINED_H_ */
diff --git a/arch/arm/mach-fh/include/mach/fh_pwm_plat.h b/arch/arm/mach-fh/include/mach/fh_pwm_plat.h
new file mode 100644
index 00000000..22c06b1f
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_pwm_plat.h
@@ -0,0 +1,9 @@
+#ifndef __FH_PWM_PLAT_H__
+#define __FH_PWM_PLAT_H__
+
+struct fh_pwm_data
+{
+ unsigned int npwm;
+};
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_rtc_plat.h b/arch/arm/mach-fh/include/mach/fh_rtc_plat.h
new file mode 100644
index 00000000..33ed0330
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_rtc_plat.h
@@ -0,0 +1,11 @@
+#ifndef __FH_RTC_PLAT_H__
+#define __FH_RTC_PLAT_H__
+
+struct fh_rtc_plat_data {
+ int lut_cof;
+ int lut_offset;
+ int tsensor_cp_default_out;
+ char *clk_name;
+};
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_sadc_plat.h b/arch/arm/mach-fh/include/mach/fh_sadc_plat.h
new file mode 100644
index 00000000..70b75a57
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_sadc_plat.h
@@ -0,0 +1,8 @@
+#ifndef __FH_SADC_PLAT_H__
+#define __FH_SADC_PLAT_H__
+
+struct fh_sadc_platform_data {
+ u32 ref_vol;
+ u32 active_bit;
+};
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_spi_plat.h b/arch/arm/mach-fh/include/mach/fh_spi_plat.h
new file mode 100644
index 00000000..a54c934d
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_spi_plat.h
@@ -0,0 +1,59 @@
+#ifndef __FH_SPI_PLAT_H__
+#define __FH_SPI_PLAT_H__
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+
+/****************************************************************************
+* #define section
+* add constant #define here if any
+***************************************************************************/
+#define SPI_MASTER_CONTROLLER_MAX_SLAVE 2
+#define SPI_TRANSFER_USE_DMA (0x77888877)
+#define SPI_DMA_PROTCTL_ENABLE (0x55)
+#define SPI_DMA_MASTER_SEL_ENABLE (0x55)
+/****************************************************************************
+* ADT section
+* add Abstract Data Type definition here
+***************************************************************************/
+
+struct fh_spi_cs {
+ u32 GPIO_Pin;
+ char *name;
+};
+
+
+
+#define ONE_WIRE_SUPPORT (1<<0)
+#define DUAL_WIRE_SUPPORT (1<<1)
+#define QUAD_WIRE_SUPPORT (1<<2)
+#define MULTI_WIRE_SUPPORT (1<<8)
+
+struct fh_spi_platform_data {
+ u32 apb_clock_in;
+ u32 slave_max_num;
+ u32 clock_source[8];
+ u32 clock_source_num;
+ u32 clock_in_use;
+ struct fh_spi_cs cs_data[SPI_MASTER_CONTROLLER_MAX_SLAVE];
+ u32 bus_no;
+ char *clk_name;
+ char *hclk_name;
+ char *pclk_name;
+ /* add support wire width*/
+ u32 ctl_wire_support;
+ /* add dma para*/
+ /*use dma, but need menuconfig open*/
+ u32 dma_transfer_enable;
+ /*related soc*/
+ u32 rx_handshake_num;
+ u32 dma_protctl_enable;
+ u32 rx_dma_channel;
+ u32 dma_protctl_data;
+ u32 dma_master_sel_enable;
+ u32 dma_master_ctl_sel;
+ u32 dma_master_mem_sel;
+};
+
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_uart_plat.h b/arch/arm/mach-fh/include/mach/fh_uart_plat.h
new file mode 100644
index 00000000..2be1e277
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_uart_plat.h
@@ -0,0 +1,47 @@
+#ifndef __FH_UART_PLAT_H__
+#define __FH_UART_PLAT_H__
+
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
+#include <linux/completion.h>
+
+struct fh_uart_dma_transfer {
+ struct dma_chan *chan;
+ struct dma_slave_config cfg;
+ struct scatterlist sgl[128];
+ unsigned int sgl_data_size[128];
+ unsigned int actual_sgl_size;
+ struct dma_async_tx_descriptor *desc;
+};
+
+struct fh_uart_dma {
+ u32 tx_dumy_buff[128];
+ u8 rx_dumy_buff[128];
+ u32 tx_dma_add;
+ u32 rx_dma_add;
+ u32 tx_hs_no;
+ u32 rx_hs_no;
+ u32 tx_dma_channel;
+ u32 rx_dma_channel;
+ u32 tx_count;
+ u32 tx_done;
+ u32 paddr;
+ u32 rx_xmit_len;
+ u32 inited;
+ struct completion rx_cmp;
+ struct fh_uart_dma_transfer dma_rx;
+ struct fh_uart_dma_transfer dma_tx;
+};
+
+struct fh_platform_uart {
+ unsigned long mapbase; /* Physical address base */
+ unsigned int fifo_size; /* UART FIFO SIZE */
+ unsigned int irq; /* Interrupt vector */
+ unsigned int uartclk; /* UART clock rate */
+ unsigned int use_dma;
+ struct fh_uart_dma *dma_info;
+};
+
+#endif
\ No newline at end of file
diff --git a/arch/arm/mach-fh/include/mach/fh_usb_plat.h b/arch/arm/mach-fh/include/mach/fh_usb_plat.h
new file mode 100644
index 00000000..e49f4ed5
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_usb_plat.h
@@ -0,0 +1,9 @@
+#ifndef __FH_USB_PLAT_H__
+#define __FH_USB_PLAT_H__
+
+struct fh_usb_platform_data {
+ char *dr_mode;
+ unsigned int vbus_pwren;
+};
+
+#endif
diff --git a/arch/arm/mach-fh/include/mach/fh_wdt_plat.h b/arch/arm/mach-fh/include/mach/fh_wdt_plat.h
new file mode 100644
index 00000000..4db09692
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/fh_wdt_plat.h
@@ -0,0 +1,11 @@
+#ifndef __FH_WDT_PLAT_H__
+#define __FH_WDT_PLAT_H__
+
+struct fh_wdt_platform_data {
+ int mode;
+#define MODE_CONTINUOUS 0
+#define MODE_DISCRETE 1
+};
+
+#endif
+
diff --git a/arch/arm/mach-fh/include/mach/io.h b/arch/arm/mach-fh/include/mach/io.h
new file mode 100644
index 00000000..80caae76
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/io.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __mem_pci(a) (a)
+#define __mem_isa(a) (a)
+
+#define FH_VIRT 0xFE000000
+
+#define VA_INTC_REG_BASE (FH_VIRT + 0x00000)
+#define VA_TIMER_REG_BASE (FH_VIRT + 0x10000)
+#define VA_UART0_REG_BASE (FH_VIRT + 0x20000)
+#define VA_PMU_REG_BASE (FH_VIRT + 0x90000)
+#define VA_UART1_REG_BASE (FH_VIRT + 0xa0000)
+#define VA_UART2_REG_BASE (FH_VIRT + 0xb0000)
+#define VA_UART3_REG_BASE (FH_VIRT + 0xc0000)
+
+#define VA_RAM_REG_BASE (FH_VIRT + 0xd0000)
+#define VA_DDRC_REG_BASE (FH_VIRT + 0xe0000)
+
+#define VA_CONSOLE_REG_BASE VA_UART0_REG_BASE
+
+#endif /* __ASM_ARCH_IO_H */
diff --git a/arch/arm/mach-fh/include/mach/pinctrl.h b/arch/arm/mach-fh/include/mach/pinctrl.h
new file mode 100644
index 00000000..56653744
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/pinctrl.h
@@ -0,0 +1,158 @@
+#ifndef PINCTRL_H_
+#define PINCTRL_H_
+#include "pinctrl_osdep.h"
+#include <linux/seq_file.h>
+
+#define MSC_3_3V (0)
+#define MSC_1_8V (1)
+
+#define PINCTRL_UNUSED (-1)
+
+#define PUPD_NONE (0)
+#define PUPD_UP (1)
+#define PUPD_DOWN (2)
+
+#define INPUT_DISABLE (0)
+#define INPUT_ENABLE (1)
+#define OUTPUT_DISABLE (0)
+#define OUTPUT_ENABLE (1)
+
+#if defined(CONFIG_MACH_FH8626V100)
+#define PUPD_DISABLE (1)
+#define PUPD_ENABLE (0)
+#define PUPD_ZERO (0)
+#else
+#define PUPD_DISABLE (0)
+#define PUPD_ENABLE (1)
+#define PUPD_ZERO (0)
+#endif
+
+#define FUNC0 (0)
+#define FUNC1 (1)
+#define FUNC2 (2)
+#define FUNC3 (3)
+#define FUNC4 (4)
+#define FUNC5 (5)
+#define FUNC6 (6)
+#define FUNC7 (7)
+#define FUNC8 (8)
+#define FUNC9 (9)
+
+
+#define NEED_CHECK_PINLIST (1)
+#define PIN_BACKUP (1<<1)
+#define PIN_RESTORE (1<<2)
+
+#define PINCTRL_FUNC(name, id, sel, pupd, ds) \
+PinCtrl_Pin PAD##id##_##name = \
+{ \
+ .pad_id = id, \
+ .func_name = #name, \
+ .reg_offset = (id * 4), \
+ .func_sel = sel, \
+ .pullup_pulldown = pupd, \
+ .driving_curr = ds, \
+ .output_enable = 1, \
+}
+
+#define PARA_COUNT_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
+#define PARA_COUNT(...) \
+ PARA_COUNT_N(0, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define PINCTRL_MUX(pname, sel, ...) \
+struct PinCtrl_Mux_##pname \
+{ \
+ int cur_pin:16; \
+ int mux_num:16; \
+ PinCtrl_Pin *mux_pin[PARA_COUNT(__VA_ARGS__)]; \
+} MUX_##pname = \
+{ \
+ .mux_pin = { __VA_ARGS__ }, \
+ .cur_pin = sel, \
+ .mux_num = PARA_COUNT(__VA_ARGS__), \
+};
+
+#define PINCTRL_DEVICE(name, count, ...) \
+typedef struct \
+{ \
+ char *dev_name; \
+ int mux_count; \
+ OS_LIST list; \
+ void *mux[count]; \
+} PinCtrl_Device_##name; \
+PinCtrl_Device_##name pinctrl_dev_##name = \
+{ \
+ .dev_name = #name, \
+ .mux_count = count, \
+ .mux = { __VA_ARGS__ }, \
+}
+
+typedef union {
+ struct {
+ unsigned int sl : 1; /*0*/
+ unsigned int : 3; /*1~3*/
+ unsigned int ds : 3; /*4~6*/
+ unsigned int msc : 1; /*7*/
+ unsigned int st : 1; /*8*/
+ unsigned int : 3; /*9~11*/
+ unsigned int ie : 1; /*12*/
+ unsigned int : 3; /*13~15*/
+ unsigned int pdn : 1; /*16*/
+ unsigned int : 3; /*17~19*/
+ unsigned int pun : 1; /*20*/
+ unsigned int : 3; /*21~23*/
+ unsigned int mfs : 4; /*24~27*/
+ unsigned int oe : 1; /*28*/
+ unsigned int : 3; /*29~31*/
+ } bit;
+ unsigned int dw;
+} PinCtrl_Register;
+
+typedef struct
+{
+ char *func_name;
+ PinCtrl_Register *reg;
+ unsigned int pad_id : 8;
+ unsigned int reg_offset : 12;
+ unsigned int func_sel : 4;
+ unsigned int input_enable : 1;
+ unsigned int output_enable : 1;
+ unsigned int pullup_pulldown : 2;
+ unsigned int volt_mode : 1;
+ unsigned int driving_curr : 3;
+}PinCtrl_Pin;
+
+typedef struct
+{
+ int cur_pin:16;
+ int mux_num:16;
+ PinCtrl_Pin *mux_pin[0];
+} PinCtrl_Mux;
+
+typedef struct
+{
+ void *vbase;
+ void *pbase;
+ PinCtrl_Pin *pinlist[PAD_NUM];
+} PinCtrl_Object;
+
+typedef struct
+{
+ char *dev_name;
+ int mux_count;
+ OS_LIST list;
+ void *mux;
+}PinCtrl_Device;
+
+void fh_pinctrl_init(unsigned int base);
+void fh_pinctrl_prt(struct seq_file *sfile);
+int fh_pinctrl_smux(char *devname, char* muxname, int muxsel, unsigned int flag);
+int fh_pinctrl_sdev(char *devname, unsigned int flag);
+int fh_pinctrl_spupd(char *pin_name, unsigned int pupd);
+int fh_pinctrl_sds(char *pin_name, unsigned int ds);
+int fh_pinctrl_set_oe(char *pin_name, unsigned int oe);
+void fh_pinctrl_init_devicelist(OS_LIST *list);
+char *fh_pinctrl_smux_backup(char *devname, char *muxname, int muxsel);
+char *fh_pinctrl_smux_restore(char *devname, char *muxname, int muxsel);
+
+#endif /* PINCTRL_H_ */
diff --git a/arch/arm/mach-fh/include/mach/pinctrl_osdep.h b/arch/arm/mach-fh/include/mach/pinctrl_osdep.h
new file mode 100644
index 00000000..52cec934
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/pinctrl_osdep.h
@@ -0,0 +1,21 @@
+#ifndef PINCTRL_OSDEP_H_
+#define PINCTRL_OSDEP_H_
+
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <mach/fh_predefined.h>
+#include <linux/string.h>
+
+#define OS_LIST_INIT LIST_HEAD_INIT
+#define OS_LIST struct list_head
+#define OS_PRINT printk
+#define OS_LIST_EMPTY INIT_LIST_HEAD
+#define OS_NULL NULL
+
+#define PINCTRL_ADD_DEVICE(name) \
+ list_add(&pinctrl_dev_##name.list, \
+ list)
+
+#define PAD_NUM (77)
+
+#endif /* PINCTRL_OSDEP_H_ */
diff --git a/arch/arm/mach-fh/include/mach/pmu.h b/arch/arm/mach-fh/include/mach/pmu.h
new file mode 100644
index 00000000..216152c1
--- /dev/null
+++ b/arch/arm/mach-fh/include/mach/pmu.h
@@ -0,0 +1,43 @@
+#ifndef _FH_PMU_H_
+#define _FH_PMU_H_
+
+#include <linux/types.h>
+#include <mach/fh_chipid.h>
+
+#include "chip.h"
+
+void fh_get_chipid(unsigned int *plat_id, unsigned int *chip_id);
+unsigned int fh_pmu_get_ptsl(void);
+unsigned int fh_pmu_get_ptsh(void);
+unsigned long long fh_get_pts64(void);
+void fh_pmu_wdt_pause(void);
+void fh_pmu_wdt_resume(void);
+void fh_pmu_usb_utmi_rst(void);
+void fh_pmu_usb_phy_rst(void);
+void fh_pmu_usb_resume(void);
+
+unsigned int fh_pmu_get_tsensor_init_data(void);
+unsigned int fh_pmu_get_ddrsize(void);
+void fh_pmu_set_sdc1_funcsel(unsigned int val);
+
+void fh_pmu_sdc_reset(int slot_id);
+void fh_pmu_mipi_reset(void);
+void fh_pmu_enc_reset(void);
+void fh_pmu_dwi2s_set_clk(unsigned int div_i2s, unsigned int div_mclk);
+void fh_pmu_eth_set_speed(unsigned int speed);
+void fh_pmu_eth_reset(void);
+void fh_pmu_restart(void);
+
+int fh_pmu_internal_ephy_reset(void);
+void fh_pmu_ephy_sel(__u32 phy_sel);
+void fh_pmu_arxc_write_A625_INT_RAWSTAT(unsigned int val);
+unsigned int fh_pmu_arxc_read_ARM_INT_RAWSTAT(void);
+void fh_pmu_arxc_write_ARM_INT_RAWSTAT(unsigned int val);
+unsigned int fh_pmu_arxc_read_ARM_INT_STAT(void);
+void fh_pmu_arxc_reset(unsigned long phy_addr);
+void fh_pmu_arxc_kickoff(void);
+
+int fh_pmu_init(void);
+
+
+#endif /* _FH_PMU_H_ */
diff --git a/arch/arm/mach-fh/pinctrl.c b/arch/arm/mach-fh/pinctrl.c
new file mode 100644
index 00000000..ec867a4f
--- /dev/null
+++ b/arch/arm/mach-fh/pinctrl.c
@@ -0,0 +1,469 @@
+#include <mach/board_config.h>
+#include <mach/pinctrl.h>
+#include <linux/module.h>
+#include <mach/io.h>
+
+#include "iopad.h"
+#include "chip.h"
+
+/* #define FH_PINCTRL_DEBUG */
+#ifdef FH_PINCTRL_DEBUG
+#define PRINT_DBG(fmt,args...) OS_PRINT(fmt,##args)
+#else
+#define PRINT_DBG(fmt,args...) do{} while(0)
+#endif
+
+static PinCtrl_Object pinctrl_obj;
+OS_LIST fh_pinctrl_devices = OS_LIST_INIT(fh_pinctrl_devices);
+
+static void fh_pinctrl_check_duplicate_pin(PinCtrl_Pin *pin, int start_pad)
+{
+ int i;
+ PinCtrl_Pin *p;
+ if (!pin)
+ return;
+ for (i = start_pad; i < PAD_NUM; i++) {
+ p = pinctrl_obj.pinlist[i];
+ if (p && p != pin && !strcmp(pin->func_name, p->func_name)) {
+ OS_PRINT("WARNING: %s already exists in pad %d\n",
+ p->func_name, p->pad_id);
+ }
+ }
+}
+
+static int fh_pinctrl_func_select(PinCtrl_Pin *pin, unsigned int flag)
+{
+ unsigned int reg;
+
+ if (!pin)
+ {
+ OS_PRINT("ERROR: pin is null\n\n");
+ return -1;
+ }
+
+ if (flag & NEED_CHECK_PINLIST)
+ {
+ if (pinctrl_obj.pinlist[pin->pad_id])
+ {
+ OS_PRINT("ERROR: pad %d has already been set\n\n", pin->pad_id);
+ return -2;
+ }
+ }
+ fh_pinctrl_check_duplicate_pin(pin, 0);
+
+ reg = GET_REG(pinctrl_obj.vbase + pin->reg_offset);
+
+ pin->reg = (PinCtrl_Register *)&reg;
+
+ pin->reg->bit.mfs = pin->func_sel;
+
+ if (pin->pullup_pulldown == PUPD_DOWN) {
+ pin->reg->bit.pun = PUPD_DISABLE;
+ pin->reg->bit.pdn = PUPD_ENABLE;
+ }
+ else if(pin->pullup_pulldown == PUPD_UP) {
+ pin->reg->bit.pun = PUPD_ENABLE;
+ pin->reg->bit.pdn = PUPD_DISABLE;
+ } else {
+ pin->reg->bit.pdn = PUPD_ZERO;
+ pin->reg->bit.pun = PUPD_ZERO;
+ }
+
+ pin->reg->bit.ds = pin->driving_curr;
+ pin->reg->bit.st = 1;
+
+ pin->reg->bit.ie = 1;
+ pin->reg->bit.oe = pin->output_enable;
+
+ SET_REG(pinctrl_obj.vbase + pin->reg_offset, pin->reg->dw);
+
+ pinctrl_obj.pinlist[pin->pad_id] = pin;
+
+ return 0;
+}
+
+static int fh_pinctrl_mux_switch(PinCtrl_Mux *mux, unsigned int flag)
+{
+ if (mux->cur_pin >= mux->mux_num) {
+ OS_PRINT("ERROR: selected function is not exist, sel_func=%d\n\n", mux->cur_pin);
+ return -3;
+ }
+
+ if (!mux->mux_pin[mux->cur_pin]) {
+ OS_PRINT("ERROR: %s mux->mux_pin[%d] has no pin\n\n",
+ mux->mux_pin[0]->func_name, mux->cur_pin);
+ return -4;
+ }
+
+ PRINT_DBG("\t%s[%d]\n", mux->mux_pin[mux->cur_pin]->func_name, mux->cur_pin);
+ return fh_pinctrl_func_select(mux->mux_pin[mux->cur_pin], flag);
+}
+
+
+static int fh_pinctrl_device_switch(PinCtrl_Device *dev, unsigned int flag)
+{
+ int i, ret;
+
+ for (i = 0; i < dev->mux_count; i++) {
+ unsigned int *mux_addr = (unsigned int *)((unsigned int)dev
+ + sizeof(*dev) - 4 + i*4);
+ PinCtrl_Mux *mux = (PinCtrl_Mux *)(*mux_addr);
+
+ ret = fh_pinctrl_mux_switch(mux, flag);
+ if (ret)
+ return ret;
+ }
+
+#if defined(CONFIG_ARCH_FH885xV200) ||\
+ defined(CONFIG_ARCH_FH865x) || \
+ defined(CONFIG_ARCH_FH8636) || \
+ defined(CONFIG_ARCH_FH8852V101)
+ if (strncmp(dev->dev_name, "SD1", 3) == 0) {
+ PinCtrl_Mux *mux = (PinCtrl_Mux *)dev->mux;
+
+#if defined(CONFIG_ARCH_FH8636) || defined(CONFIG_ARCH_FH8852V101)
+ static int sd1_func_map[] = {1, 0, 2}; /* func sel map */
+#else
+ static int sd1_func_map[] = {0, 1, 2, 3}; /* func sel map */
+#endif
+ /* for some platform, set SD1_FUNC_SEL after all mux switch */
+ SET_REG(VA_PMU_REG_BASE + REG_PMU_SD1_FUNC_SEL,
+ sd1_func_map[mux->cur_pin]);
+ }
+#endif
+ return 0;
+}
+
+static PinCtrl_Device * fh_pinctrl_get_device_by_name(char *name)
+{
+ PinCtrl_Device *dev = OS_NULL;
+
+ list_for_each_entry(dev, &fh_pinctrl_devices, list)
+ {
+ if (!strcmp(name, dev->dev_name))
+ {
+ return dev;
+ }
+ }
+
+ return 0;
+}
+
+static PinCtrl_Mux *fh_pinctrl_get_mux_by_name(char *mux_name)
+{
+ int i;
+ PinCtrl_Device *dev;
+
+ list_for_each_entry(dev, &fh_pinctrl_devices, list) {
+ for (i = 0; i < dev->mux_count; i++) {
+ unsigned int *mux_addr = (unsigned int *)(
+ (unsigned int)dev + sizeof(*dev) - 4 + i*4);
+ PinCtrl_Mux *mux = (PinCtrl_Mux *)(*mux_addr);
+
+ if (!strcmp(mux_name, mux->mux_pin[0]->func_name))
+ return mux;
+ }
+ }
+
+ return NULL;
+}
+
+int fh_pinctrl_check_pinlist(void)
+{
+ int i;
+
+ for (i=0; i<PAD_NUM; i++) {
+ if (!pinctrl_obj.pinlist[i])
+ PRINT_DBG("ERROR: pad %d is still empty\n", i);
+ }
+
+ return 0;
+}
+
+static int fh_pinctrl_init_devices(char **devlist,
+ int listsize, unsigned int flag)
+{
+ int i, ret;
+ PinCtrl_Device *dev;
+
+ memset(pinctrl_obj.pinlist, 0, sizeof(pinctrl_obj.pinlist));
+
+ for (i = 0; i < listsize; i++)
+ {
+ if (!devlist[i])
+ continue;
+ dev = fh_pinctrl_get_device_by_name(devlist[i]);
+
+ if (!dev) {
+ OS_PRINT("ERROR: cannot find device %s\n", devlist[i]);
+ return -5;
+ }
+
+ PRINT_DBG("%s:\n", dev->dev_name);
+ ret = fh_pinctrl_device_switch(dev, flag);
+ PRINT_DBG("\n");
+ if (ret)
+ return ret;
+
+ }
+
+ fh_pinctrl_check_pinlist();
+
+ return 0;
+
+}
+
+static void fh_pinctrl_init_pin(void)
+{
+ int i;
+
+ for (i = 0; i < PAD_NUM; i++)
+ {
+ PinCtrl_Pin *pin = pinctrl_obj.pinlist[i];
+
+ if (!pin) {
+ PinCtrl_Register reg;
+
+ PRINT_DBG("ERROR: pad %d is empty\n", i);
+ reg.dw = GET_REG(pinctrl_obj.vbase + i * 4);
+ reg.bit.ie = 0;
+ reg.bit.oe = 0;
+ SET_REG(pinctrl_obj.vbase + i * 4, reg.dw);
+ continue;
+ }
+ pin->reg->dw = GET_REG(pinctrl_obj.vbase +
+ pin->reg_offset);
+
+ pin->input_enable = pin->reg->bit.ie;
+ pin->output_enable = pin->reg->bit.oe;
+ }
+}
+
+void fh_pinctrl_init(unsigned int base)
+{
+ pinctrl_obj.vbase = pinctrl_obj.pbase = (void *)base;
+
+ fh_pinctrl_init_devicelist(&fh_pinctrl_devices);
+ fh_pinctrl_init_devices(fh_pinctrl_selected_devices,
+ ARRAY_SIZE(fh_pinctrl_selected_devices),
+ NEED_CHECK_PINLIST);
+ fh_pinctrl_init_pin();
+
+#if defined(CONFIG_ARCH_FH885xV200) ||\
+ defined(CONFIG_ARCH_FH865x)
+ {
+ int boot_mode = GET_REG(VA_PMU_REG_BASE + REG_PMU_BOOT_MODE);
+
+ /* REG_PMU_RESERVED0=4, boot from emmc */
+ if (boot_mode == 4)
+ fh_pinctrl_sdev("SD1_EMMC", 0);
+ }
+#endif
+}
+
+void fh_pinctrl_prt(struct seq_file *sfile)
+{
+ int i;
+ static char *pupds[3] = {
+ [PUPD_NONE] = "none",
+ [PUPD_UP] = "up",
+ [PUPD_DOWN] = "down",
+ };
+
+ seq_printf(sfile, "%2s\t%8s\t%4s\t%8s\t%4s\t%4s\t%4s\t%4s\t%4s\n",
+ "id", "name", "addr", "reg", "sel", "ie", "oe", "pupd", "ds");
+ for (i = 0; i < PAD_NUM; i++) {
+ if (!pinctrl_obj.pinlist[i]) {
+ OS_PRINT("ERROR: pad %d is empty\n", i);
+ continue;
+ }
+ fh_pinctrl_check_duplicate_pin(pinctrl_obj.pinlist[i], i+1);
+ seq_printf(sfile, "%02d\t%8s\t0x%04x\t0x%08x\t%04d\t%04d\t%04d\t%4s\t%04d\n",
+ pinctrl_obj.pinlist[i]->pad_id,
+ pinctrl_obj.pinlist[i]->func_name,
+ pinctrl_obj.pinlist[i]->reg_offset + 0x80,
+ GET_REG(pinctrl_obj.vbase + pinctrl_obj.pinlist[i]->reg_offset),
+ pinctrl_obj.pinlist[i]->func_sel,
+ pinctrl_obj.pinlist[i]->input_enable,
+ pinctrl_obj.pinlist[i]->output_enable,
+ pupds[pinctrl_obj.pinlist[i]->pullup_pulldown],
+ pinctrl_obj.pinlist[i]->driving_curr);
+ }
+
+}
+EXPORT_SYMBOL(fh_pinctrl_prt);
+
+
+int fh_pinctrl_smux(char *devname, char* muxname, int muxsel, unsigned int flag)
+{
+ PinCtrl_Device *dev;
+ int i, ret;
+ PinCtrl_Mux *foundmux = NULL;
+ char *oldfunc = NULL;
+
+ if (flag & PIN_RESTORE) {
+ foundmux = fh_pinctrl_get_mux_by_name(muxname);
+ if (foundmux == NULL) {
+ OS_PRINT("ERROR: PIN_RESTORE, cannot found mux: %s\n",
+ muxname);
+ return -10;
+ }
+ goto mux_switch;
+ }
+
+ dev = fh_pinctrl_get_device_by_name(devname);
+
+ if (!dev) {
+ OS_PRINT("ERROR: cannot find device %s\n", devname);
+ return -4;
+ }
+
+ for (i = 0; i < dev->mux_count; i++) {
+ unsigned int *mux_addr = (unsigned int *)((unsigned int)dev
+ + sizeof(*dev) - 4 + i*4);
+ PinCtrl_Mux *mux = (PinCtrl_Mux *)(*mux_addr);
+
+ if (!strcmp(muxname, mux->mux_pin[0]->func_name)) {
+ foundmux = mux;
+ mux->cur_pin = muxsel;
+ goto mux_switch;
+ }
+ }
+
+ if (i == dev->mux_count) {
+ OS_PRINT("ERROR: cannot find mux %s of device %s\n",
+ muxname, devname);
+ return -6;
+ }
+
+mux_switch:
+ if (flag & PIN_BACKUP) {
+ int id = foundmux->mux_pin[foundmux->cur_pin]->pad_id;
+ PinCtrl_Pin *pin = pinctrl_obj.pinlist[id];
+
+ if (pin == NULL) {
+ OS_PRINT("ERROR: PIN_BACKUP, oldpin is null\n");
+ return 0;
+ }
+ oldfunc = pin->func_name;
+ }
+ ret = fh_pinctrl_mux_switch(foundmux, flag);
+ if (flag & PIN_BACKUP)
+ ret = (int)oldfunc;
+
+ fh_pinctrl_check_pinlist();
+
+ return ret;
+}
+EXPORT_SYMBOL(fh_pinctrl_smux);
+
+char *fh_pinctrl_smux_backup(char *devname, char *muxname, int muxsel)
+{
+ return (char *)fh_pinctrl_smux(devname, muxname, muxsel, PIN_BACKUP);
+}
+
+char *fh_pinctrl_smux_restore(char *devname, char *muxname, int muxsel)
+{
+ return (char *)fh_pinctrl_smux(devname, muxname, muxsel, PIN_RESTORE);
+}
+
+EXPORT_SYMBOL(fh_pinctrl_smux_backup);
+EXPORT_SYMBOL(fh_pinctrl_smux_restore);
+
+
+int fh_pinctrl_sdev(char *devname, unsigned int flag)
+{
+ PinCtrl_Device *dev;
+ int ret;
+
+ dev = fh_pinctrl_get_device_by_name(devname);
+ if (!dev) {
+ OS_PRINT("ERROR: cannot find device %s\n", devname);
+ return -7;
+ }
+
+ OS_PRINT("%s:\n", dev->dev_name);
+ ret = fh_pinctrl_device_switch(dev, flag);
+ OS_PRINT("\n");
+ if (ret)
+ return ret;
+
+ fh_pinctrl_check_pinlist();
+
+ return 0;
+}
+EXPORT_SYMBOL(fh_pinctrl_sdev);
+
+static PinCtrl_Pin *fh_pinctrl_get_pin_by_name(char *pin_name)
+{
+ int i;
+ PinCtrl_Pin *pin = NULL;
+
+ for (i = 0; i < PAD_NUM; i++) {
+ pin = pinctrl_obj.pinlist[i];
+ if (!pin || !pin->func_name)
+ continue;
+ if (!strcmp(pin->func_name, pin_name))
+ return pin;
+ }
+
+ return NULL;
+}
+
+int fh_pinctrl_spupd(char *pin_name, unsigned int pupd)
+{
+ PinCtrl_Pin *pin = NULL;
+
+ pin = fh_pinctrl_get_pin_by_name(pin_name);
+
+ if (!pin) {
+ OS_PRINT("ERROR: cannot find pin %s\n", pin_name);
+ return -ENXIO;
+ }
+
+ pin->pullup_pulldown = pupd;
+ return fh_pinctrl_func_select(pin, 0);
+}
+EXPORT_SYMBOL(fh_pinctrl_spupd);
+
+int fh_pinctrl_sds(char *pin_name, unsigned int ds)
+{
+ PinCtrl_Pin *pin = NULL;
+
+ if (ds > 7) {
+ OS_PRINT("ds val is in [0-7]\n");
+ return -EINVAL;
+ }
+
+ pin = fh_pinctrl_get_pin_by_name(pin_name);
+
+ if (!pin) {
+ OS_PRINT("ERROR: cannot find pin %s\n", pin_name);
+ return -ENXIO;
+ }
+
+ pin->driving_curr = ds;
+ return fh_pinctrl_func_select(pin, 0);
+}
+EXPORT_SYMBOL(fh_pinctrl_sds);
+
+int fh_pinctrl_set_oe(char *pin_name, unsigned int oe)
+{
+ PinCtrl_Pin *pin = NULL;
+
+ if (oe > 1) {
+ OS_PRINT("oe is 0 or 1\n");
+ return -1;
+ }
+
+ pin = fh_pinctrl_get_pin_by_name(pin_name);
+
+ if (!pin) {
+ OS_PRINT("ERROR: cannot find pin %s\n", pin_name);
+ return -2;
+ }
+
+ pin->output_enable = oe;
+ return fh_pinctrl_func_select(pin, 0);
+}
+EXPORT_SYMBOL(fh_pinctrl_set_oe);
diff --git a/arch/arm/mach-fh/platsmp.c b/arch/arm/mach-fh/platsmp.c
new file mode 100644
index 00000000..935ae4e7
--- /dev/null
+++ b/arch/arm/mach-fh/platsmp.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ * Based on arch/arm/mach-vexpress/platsmp.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include <asm/mach/map.h>
+
+#include "core.h"
+
+static void __iomem *ctrl_base;
+static int use_emc;
+
+
+void fhca7_set_cpu_jump(int cpu, void *jump_addr)
+{
+ cpu = cpu_logical_map(cpu);
+ if (!cpu || !ctrl_base)
+ return;
+ if (use_emc == 1)
+ writel_relaxed(virt_to_phys(jump_addr), ctrl_base + 0x2000);
+ else
+ writel_relaxed(virt_to_phys(jump_addr),
+ ctrl_base + COH_FUN_BASE);
+}
+
+int fhca7_get_cpu_jump(int cpu)
+{
+ cpu = cpu_logical_map(cpu);
+ if (!cpu || !ctrl_base)
+ return 0;
+ if (use_emc == 1)
+ return readl_relaxed(ctrl_base + 0x2000);
+ else
+ return readl_relaxed(ctrl_base + COH_FUN_BASE);
+}
+
+
+
+static void __init fhca7_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *np = NULL;
+ void __iomem *pmu_base;
+
+ if (!ctrl_base) {
+ np = of_find_compatible_node(NULL, NULL, "fh,fh-pmu");
+ if (!np) {
+ pr_err("failed to find fh,fh-pmu node\n");
+ return;
+ }
+ pmu_base = of_iomap(np, 0);
+ if (!pmu_base) {
+ pr_err("failed to map address\n");
+ return;
+ }
+ if (readl(pmu_base + COH_MAGIC) != MPCORE_COH_MAGIC) {
+ use_emc = 1;
+ pr_err("mismatch magic ,return to emc to find coh-pen\n");
+ np = of_find_compatible_node(NULL, NULL, "fh,emc-ram");
+ if (!np) {
+ pr_err("failed to find fh,emc-ramnode\n");
+ return;
+ }
+ ctrl_base = of_iomap(np, 0);
+ if (!ctrl_base) {
+ pr_err("failed to map address\n");
+ return;
+ }
+ } else {
+ ctrl_base = pmu_base;
+ use_emc = 0;
+ }
+ }
+}
+
+static int fhca7_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ fhca7_set_cpu(cpu, true);
+ fhca7_set_cpu_jump(cpu, secondary_startup);
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+ return 0;
+}
+
+static const struct smp_operations fhca7_smp_ops __initconst = {
+ .smp_prepare_cpus = fhca7_smp_prepare_cpus,
+ .smp_boot_secondary = fhca7_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_die = fhca7_cpu_die,
+ .cpu_kill = fhca7_cpu_kill,
+#endif
+};
+
+
+CPU_METHOD_OF_DECLARE(fhca7_smp, "fh,fh-ca7-smp", &fhca7_smp_ops);
diff --git a/arch/arm/mach-fh/pmu.c b/arch/arm/mach-fh/pmu.c
new file mode 100644
index 00000000..ac4d4161
--- /dev/null
+++ b/arch/arm/mach-fh/pmu.c
@@ -0,0 +1,583 @@
+#include <linux/types.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <mach/io.h>
+#include <linux/io.h>
+#include "chip.h"
+#include "soc.h"
+
+static int s_pmu_inited = 0;
+static void __iomem *fh_pmu_regs = NULL;
+
+#ifndef INTERNAL_PHY
+#define INTERNAL_PHY 0x55
+#endif
+#ifndef EXTERNAL_PHY
+#define EXTERNAL_PHY 0xaa
+#endif
+
+void fh_pmu_set_reg(unsigned int offset, unsigned int data)
+{
+
+ if (offset > FH_PMU_REG_SIZE) {
+ pr_err("fh_pmu_set_reg: offset is out of range");
+ return;
+ }
+
+ writel(data, fh_pmu_regs + offset);
+}
+EXPORT_SYMBOL(fh_pmu_set_reg);
+
+unsigned int fh_pmu_get_reg(unsigned int offset)
+{
+
+ if (offset > FH_PMU_REG_SIZE) {
+ pr_err("fh_pmu_get_reg: offset is out of range");
+ return 0;
+ }
+ return readl(fh_pmu_regs + offset);
+}
+EXPORT_SYMBOL(fh_pmu_get_reg);
+
+void fh_pmu_set_reg_m(unsigned int offset, unsigned int data, unsigned int mask)
+{
+ fh_pmu_set_reg(offset, (fh_pmu_get_reg(offset) & (~(mask))) |
+ ((data) & (mask)));
+}
+EXPORT_SYMBOL(fh_pmu_set_reg_m);
+
+void fh_get_chipid(unsigned int *plat_id, unsigned int *chip_id)
+{
+ unsigned int _plat_id = 0;
+
+ _plat_id = fh_pmu_get_reg(REG_PMU_CHIP_ID);
+ if (plat_id != NULL)
+ *plat_id = _plat_id;
+
+ if (chip_id != NULL)
+ *chip_id = fh_pmu_get_reg(REG_PMU_IP_VER);
+}
+EXPORT_SYMBOL(fh_get_chipid);
+
+unsigned int fh_pmu_get_ptsl(void)
+{
+ fh_pmu_set_reg(REG_PMU_PTSLO, 0x01);
+ return fh_pmu_get_reg(REG_PMU_PTSLO);
+}
+EXPORT_SYMBOL(fh_pmu_get_ptsl);
+
+unsigned int fh_pmu_get_ptsh(void)
+{
+ fh_pmu_set_reg(REG_PMU_PTSLO, 0x01);
+ return fh_pmu_get_reg(REG_PMU_PTSHI);
+}
+EXPORT_SYMBOL(fh_pmu_get_ptsh);
+
+unsigned long long fh_get_pts64(void)
+{
+ unsigned int high, low;
+ unsigned long long pts64;
+
+ fh_pmu_set_reg(REG_PMU_PTSLO, 0x01);
+ high = fh_pmu_get_reg(REG_PMU_PTSHI);
+ low = fh_pmu_get_reg(REG_PMU_PTSLO);
+ pts64 = (((unsigned long long)high)<<32)|((unsigned long long)low);
+ return pts64;
+}
+EXPORT_SYMBOL(fh_get_pts64);
+
+void fh_pmu_wdt_pause(void)
+{
+ unsigned int reg;
+
+ reg = fh_pmu_get_reg(REG_PMU_WDT_CTRL);
+ reg |= 0x100;
+ fh_pmu_set_reg(REG_PMU_WDT_CTRL, reg);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_wdt_pause);
+
+void fh_pmu_wdt_resume(void)
+{
+ unsigned int reg;
+
+ reg = fh_pmu_get_reg(REG_PMU_WDT_CTRL);
+ reg &= ~(0x100);
+ fh_pmu_set_reg(REG_PMU_WDT_CTRL, reg);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_wdt_resume);
+
+void fh_pmu_usb_utmi_rst(void)
+{
+ unsigned int pmu_reg;
+
+ pmu_reg = fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL);
+ pmu_reg &= ~(USB_UTMI_RST_BIT);
+ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, pmu_reg);
+ pmu_reg = fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL);
+ mdelay(1);
+ pmu_reg |= USB_UTMI_RST_BIT;
+ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, pmu_reg);
+ pmu_reg = fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL);
+ msleep(20);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_usb_utmi_rst);
+
+void fh_pmu_usb_phy_rst(void)
+{
+ unsigned int pmu_reg;
+
+ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS1);
+ pmu_reg &= (~USB_IDDQ_PWR_BIT);
+ fh_pmu_set_reg(REG_PMU_USB_SYS1, pmu_reg);
+ mdelay(1);
+ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS);
+ pmu_reg |= (USB_PHY_RST_BIT);
+ fh_pmu_set_reg(REG_PMU_USB_SYS, pmu_reg);
+ mdelay(1);
+ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS);
+ pmu_reg &= (~USB_PHY_RST_BIT);
+ fh_pmu_set_reg(REG_PMU_USB_SYS, pmu_reg);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_usb_phy_rst);
+
+void fh_pmu_usb_resume(void)
+{
+ unsigned int pmu_reg;
+
+ pmu_reg = fh_pmu_get_reg(REG_PMU_USB_SYS);
+ pmu_reg |= (USB_SLEEP_MODE_BIT);
+ fh_pmu_set_reg(REG_PMU_USB_SYS, pmu_reg);
+ mdelay(1);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_usb_resume);
+
+void _pmu_main_reset(unsigned int reg, unsigned int retry, unsigned int udelay)
+{
+ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, reg);
+
+ while (fh_pmu_get_reg(REG_PMU_SWRST_MAIN_CTRL) != 0xffffffff) {
+ if (retry-- <= 0)
+ return;
+
+ udelay(udelay);
+ }
+}
+
+#if defined(CONFIG_MACH_FH8856) || \
+ defined(CONFIG_MACH_FH8852) || \
+ defined(CONFIG_MACH_FH8626V100)
+
+void _pmu_axi_reset(unsigned int reg, unsigned int retry, unsigned int udelay)
+{
+ fh_pmu_set_reg(REG_PMU_SWRST_AXI_CTRL, reg);
+
+ while (fh_pmu_get_reg(REG_PMU_SWRST_AXI_CTRL) != 0xffffffff) {
+ if (retry-- <= 0)
+ return;
+
+ udelay(udelay);
+ }
+}
+#endif
+
+void _pmu_ahb_reset(unsigned int reg, unsigned int retry, unsigned int udelay)
+{
+ fh_pmu_set_reg(REG_PMU_SWRST_AHB_CTRL, reg);
+
+ while (fh_pmu_get_reg(REG_PMU_SWRST_AHB_CTRL) != 0xffffffff) {
+ if (retry-- <= 0)
+ return;
+
+ udelay(udelay);
+ }
+}
+
+void _pmu_apb_reset(unsigned int reg, unsigned int retry, unsigned int udelay)
+{
+ fh_pmu_set_reg(REG_PMU_SWRST_APB_CTRL, reg);
+
+ while (fh_pmu_get_reg(REG_PMU_SWRST_APB_CTRL) != 0xffffffff) {
+ if (retry-- <= 0)
+ return;
+
+ udelay(udelay);
+ }
+}
+
+void _pmu_nsr_reset(unsigned int reg, unsigned int reset_time)
+{
+ fh_pmu_set_reg(REG_PMU_SWRSTN_NSR, reg);
+ udelay(reset_time);
+ fh_pmu_set_reg(REG_PMU_SWRSTN_NSR, 0xFFFFFFFF);
+}
+
+void fh_pmu_sdc_reset(int slot_id)
+{
+ unsigned int reg = 0;
+
+ if (slot_id == 1)
+ reg = ~(1 << SDC1_HRSTN_BIT);
+ else if (slot_id == 0)
+ reg = ~(1 << SDC0_HRSTN_BIT);
+ else
+ reg = 0;
+
+ _pmu_ahb_reset(reg, 1000, 1);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_sdc_reset);
+
+void fh_pmu_mipi_reset(void)
+{
+ _pmu_apb_reset(~(1 << MIPIW_PRSTN_BIT | 1 << MIPIC_PRSTN_BIT), 1000, 1);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_mipi_reset);
+
+void fh_pmu_enc_reset(void)
+{
+#if !defined(CONFIG_ARCH_FH8626V100) \
+ && !defined(CONFIG_ARCH_FH8636) \
+ && !defined(CONFIG_ARCH_FH8852V101)
+ _pmu_ahb_reset(~(1 << VCU_HRSTN_BIT), 100, 10);
+#endif
+}
+EXPORT_SYMBOL_GPL(fh_pmu_enc_reset);
+
+void fh_pmu_dwi2s_set_clk(unsigned int div_i2s, unsigned int div_mclk)
+{
+#if !defined(CONFIG_ARCH_FH8636) && !defined(CONFIG_ARCH_FH8852V101)
+ unsigned int reg;
+
+ reg = fh_pmu_get_reg(PMU_DWI2S_CLK_DIV_REG);
+ reg &= ~(0xffff << PMU_DWI2S_CLK_DIV_SHIFT);
+ reg |= ((div_i2s-1) << 8 | (div_mclk-1)) << PMU_DWI2S_CLK_DIV_SHIFT;
+ fh_pmu_set_reg(PMU_DWI2S_CLK_DIV_REG, reg);
+
+ /* i2s_clk switch to PLLVCO */
+ reg = fh_pmu_get_reg(PMU_DWI2S_CLK_SEL_REG);
+ reg &= ~(1 << PMU_DWI2S_CLK_SEL_SHIFT);
+ reg |= 1 << PMU_DWI2S_CLK_SEL_SHIFT;
+ fh_pmu_set_reg(PMU_DWI2S_CLK_SEL_REG, reg);
+#endif
+}
+EXPORT_SYMBOL_GPL(fh_pmu_dwi2s_set_clk);
+
+void fh_pmu_eth_set_speed(unsigned int speed)
+{
+ unsigned int reg;
+
+ reg = fh_pmu_get_reg(PMU_RMII_SPEED_MODE);
+ if (speed == 10)
+ reg &= ~(FH_GMAC_SPEED_100M);
+ else if (speed == 100)
+ reg |= FH_GMAC_SPEED_100M;
+ else
+ printk(KERN_ERR"ERROR: wrong param for emac set speed, %d\n",
+ speed);
+
+ fh_pmu_set_reg(PMU_RMII_SPEED_MODE, reg);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_eth_set_speed);
+
+void fh_pmu_eth_reset(void)
+{
+ _pmu_ahb_reset(~(1 << EMAC_HRSTN_BIT), 1000, 1);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_eth_reset);
+
+void fh_pmu_restart(void)
+{
+ fh_pmu_set_reg(REG_PMU_SWRST_MAIN_CTRL, 0x7fffffff);
+}
+
+
+unsigned int fh_pmu_get_tsensor_init_data(void)
+{
+#if defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x) || \
+defined(CONFIG_ARCH_FH8636) || \
+defined(CONFIG_ARCH_FH8852V101)
+ return fh_pmu_get_reg(REG_PMU_RTC_PARAM);
+#else
+ return 0;
+#endif
+}
+EXPORT_SYMBOL_GPL(fh_pmu_get_tsensor_init_data);
+
+unsigned int fh_pmu_get_ddrsize(void)
+{
+#if defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x) || \
+defined(CONFIG_ARCH_FH8636) || \
+defined(CONFIG_ARCH_FH8852V101)
+ return fh_pmu_get_reg(REG_PMU_DDR_SIZE);
+#else
+ return 0;
+#endif
+}
+EXPORT_SYMBOL_GPL(fh_pmu_get_ddrsize);
+
+#if defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x)
+
+#define REFIX_TRAIN_DATA_OFFSET (0)
+#define MIN_TRAINING_DATA -8
+#define MAX_TRAINING_DATA 7
+int __refix_train_data(int *pdata, int offset)
+{
+ int temp_data;
+
+ temp_data = *pdata;
+ temp_data &= INSIDE_PHY_TRAINING_MASK;
+
+ if (temp_data & 0x08)
+ temp_data = (~INSIDE_PHY_TRAINING_MASK) | temp_data;
+
+ temp_data += offset;
+
+ if (temp_data < MIN_TRAINING_DATA || temp_data > MAX_TRAINING_DATA) {
+ pr_err("cal data [%d] should limit in [%d , %d]\n",
+ temp_data, MIN_TRAINING_DATA, MAX_TRAINING_DATA);
+ return -1;
+ }
+ temp_data &= INSIDE_PHY_TRAINING_MASK;
+
+ *pdata = temp_data;
+ return 0;
+}
+
+void refix_train_data(int *pdata)
+{
+ __refix_train_data(pdata, REFIX_TRAIN_DATA_OFFSET);
+}
+#endif
+
+int fh_pmu_internal_ephy_reset(void)
+{
+#if defined CONFIG_FH_EPHY
+ pr_err("fh_pmu_internal_ephy_reset v2 get in...\n");
+ //add internal phy reset code below...
+#elif defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x)
+ int train_data;
+ /*reset sunplus phy */
+ /*
+ * ephy shutdown: ---____________________________
+ * ephy rst : ___|<=L_10ms=>|--|<=H_12us=>|--
+ * ephy clkin : _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
+ */
+ /* pull up shut down first.. */
+ fh_pmu_set_reg_m(REG_PMU_ETHPHY_REG0,
+ 1 << INSIDE_PHY_SHUTDOWN_BIT_POS,
+ 1 << INSIDE_PHY_SHUTDOWN_BIT_POS);
+
+ udelay(5);
+ /* pull down shut down and rst for 10ms. */
+ fh_pmu_set_reg_m(REG_PMU_ETHPHY_REG0, 0,
+ 1 << INSIDE_PHY_SHUTDOWN_BIT_POS);
+
+ fh_pmu_set_reg_m(REG_PMU_SWRSTN_NSR, 0,
+ 1 << INSIDE_PHY_RST_BIT_POS);
+
+ mdelay(10);
+ /* pull up rst for 12us. */
+ fh_pmu_set_reg_m(REG_PMU_SWRSTN_NSR,
+ 1 << INSIDE_PHY_RST_BIT_POS,
+ 1 << INSIDE_PHY_RST_BIT_POS);
+
+ udelay(12);
+
+ train_data = fh_pmu_get_reg(REG_PMU_EPHY_PARAM);
+ if (train_data & (1 << TRAINING_EFUSE_ACTIVE_BIT_POS)) {
+ /* train_data */
+ refix_train_data(&train_data);
+ pr_info("ephy: training data is :%x\n",
+ train_data);
+ fh_pmu_set_reg_m(REG_PMU_ETHPHY_REG0,
+ (train_data & INSIDE_PHY_TRAINING_MASK)
+ << INSIDE_PHY_TRAINING_BIT_POS,
+ INSIDE_PHY_TRAINING_MASK << INSIDE_PHY_TRAINING_BIT_POS);
+ } else{
+ /* todo set default value...*/
+ train_data = 0;
+ pr_info("ephy: no training data, use default:%x\n",
+ train_data);
+ /* train_data */
+ fh_pmu_set_reg_m(REG_PMU_ETHPHY_REG0,
+ train_data << INSIDE_PHY_TRAINING_BIT_POS,
+ INSIDE_PHY_TRAINING_MASK << INSIDE_PHY_TRAINING_BIT_POS);
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(fh_pmu_internal_ephy_reset);
+
+void fh_pmu_ephy_sel(__u32 phy_sel)
+{
+#if defined CONFIG_FH_EPHY
+ pr_err("fh_pmu_ephy_sel v2 get in...\n");
+ //add multi phy sel code below...
+
+#elif defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x)
+ fh_pmu_set_reg_m(REG_PMU_CLK_SEL,
+ 1 << CLK_SCAN_BIT_POS, 1 << CLK_SCAN_BIT_POS);
+
+ if (phy_sel == EXTERNAL_PHY) {
+ /* close inside phy */
+ fh_pmu_set_reg_m(REG_PMU_ETHPHY_REG0,
+ 0 << INSIDE_PHY_ENABLE_BIT_POS, 1 << INSIDE_PHY_ENABLE_BIT_POS);
+ /* gate inside phy */
+ fh_pmu_set_reg_m(REG_PMU_CLK_GATE1,
+ 1 << INSIDE_CLK_GATE_BIT_POS,
+ 1 << INSIDE_CLK_GATE_BIT_POS);
+ /* set div */
+ fh_pmu_set_reg_m(REG_PMU_CLK_DIV6,
+ 1 << MAC_REF_CLK_DIV_BIT_POS,
+ MAC_REF_CLK_DIV_MASK << MAC_REF_CLK_DIV_BIT_POS);
+ /* set pad */
+ /* eth ref clk out Ungate */
+ fh_pmu_set_reg_m(REG_PMU_CLK_GATE,
+ 0 << ETH_REF_CLK_OUT_GATE_BIT_POS,
+ 1 << ETH_REF_CLK_OUT_GATE_BIT_POS);
+ /* eth rmii clk Ungate */
+ fh_pmu_set_reg_m(REG_PMU_CLK_GATE,
+ 0 << ETH_RMII_CLK_OUT_GATE_BIT_POS,
+ 1 << ETH_RMII_CLK_OUT_GATE_BIT_POS);
+ /* switch mac clk in */
+ fh_pmu_set_reg_m(REG_PMU_CLK_SEL,
+ 1 << IN_OR_OUT_PHY_SEL_BIT_POS,
+ 1 << IN_OR_OUT_PHY_SEL_BIT_POS);
+ } else {
+ /* inside phy enable */
+ fh_pmu_set_reg_m(REG_PMU_ETHPHY_REG0,
+ 1 << INSIDE_PHY_ENABLE_BIT_POS,
+ 1 << INSIDE_PHY_ENABLE_BIT_POS);
+ /* set pad no need */
+ /* eth ref clk out gate */
+ fh_pmu_set_reg_m(REG_PMU_CLK_GATE,
+ 1 << ETH_REF_CLK_OUT_GATE_BIT_POS,
+ 1 << ETH_REF_CLK_OUT_GATE_BIT_POS);
+ /* eth rmii clk gate */
+ fh_pmu_set_reg_m(REG_PMU_CLK_GATE,
+ 1 << ETH_RMII_CLK_OUT_GATE_BIT_POS,
+ 1 << ETH_RMII_CLK_OUT_GATE_BIT_POS);
+ /* inside phy clk Ungate */
+ fh_pmu_set_reg_m(REG_PMU_CLK_GATE1,
+ 0 << INSIDE_CLK_GATE_BIT_POS,
+ 1 << INSIDE_CLK_GATE_BIT_POS);
+ /* int rmii refclk mux */
+ fh_pmu_set_reg_m(REG_PMU_CLK_SEL,
+ 0 << IN_OR_OUT_PHY_SEL_BIT_POS,
+ 1 << IN_OR_OUT_PHY_SEL_BIT_POS);
+ }
+#else
+ return;
+#endif
+}
+EXPORT_SYMBOL(fh_pmu_ephy_sel);
+
+void fh_pmu_set_sdc1_funcsel(unsigned int val)
+{
+#if defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x) || \
+defined(CONFIG_ARCH_FH8636) || \
+defined(CONFIG_ARCH_FH8852V101)
+ fh_pmu_set_reg(REG_PMU_SD1_FUNC_SEL, val);
+#endif
+}
+EXPORT_SYMBOL_GPL(fh_pmu_set_sdc1_funcsel);
+
+void fh_pmu_arxc_write_A625_INT_RAWSTAT(unsigned int val)
+{
+ fh_pmu_set_reg(PMU_A625_INT_RAWSTAT, val);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_arxc_write_A625_INT_RAWSTAT);
+
+unsigned int fh_pmu_arxc_read_ARM_INT_RAWSTAT(void)
+{
+ return fh_pmu_get_reg(PMU_ARM_INT_RAWSTAT);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_arxc_read_ARM_INT_RAWSTAT);
+
+void fh_pmu_arxc_write_ARM_INT_RAWSTAT(unsigned int val)
+{
+ fh_pmu_set_reg(PMU_ARM_INT_RAWSTAT, val);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_arxc_write_ARM_INT_RAWSTAT);
+
+unsigned int fh_pmu_arxc_read_ARM_INT_STAT(void)
+{
+ return fh_pmu_get_reg(PMU_ARM_INT_STAT);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_arxc_read_ARM_INT_STAT);
+
+void fh_pmu_arxc_reset(unsigned long phy_addr)
+{
+ unsigned int arc_addr;
+
+ /*ARC Reset*/
+ fh_pmu_set_reg(REG_PMU_SWRSTN_NSR, ~(1<<ARC_RSTN_BIT));
+
+ arc_addr = ((phy_addr & 0xffff) << 16) | (phy_addr >> 16);
+
+ fh_pmu_set_reg(REG_PMU_A625BOOT0, 0x7940266B);
+ /* Configure ARC Bootcode start address */
+ fh_pmu_set_reg(REG_PMU_A625BOOT1, arc_addr);
+ fh_pmu_set_reg(REG_PMU_A625BOOT2, 0x0F802020);
+ fh_pmu_set_reg(REG_PMU_A625BOOT3, arc_addr);
+
+ /*clear ARC ready flag*/
+ fh_pmu_arxc_write_ARM_INT_RAWSTAT(0);
+
+ /* don't let ARC run when release ARC */
+ fh_pmu_set_reg(REG_PMU_A625_START_CTRL, 0);
+ udelay(2);
+
+ /* ARC reset released */
+ fh_pmu_set_reg(REG_PMU_SWRSTN_NSR, 0xFFFFFFFF);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_arxc_reset);
+
+void fh_pmu_arxc_kickoff(void)
+{
+ //start ARC625
+ fh_pmu_set_reg(REG_PMU_A625_START_CTRL, 0x10);
+}
+EXPORT_SYMBOL_GPL(fh_pmu_arxc_kickoff);
+
+#ifdef CONFIG_USE_OF
+static const struct of_device_id fh_pmu_match[] = {
+ {
+ .compatible = "fh,fh-pmu",
+ },
+ {},
+};
+#endif
+
+int fh_pmu_init(void)
+{
+
+#ifdef CONFIG_USE_OF
+ struct device_node *np;
+#endif
+
+ if (s_pmu_inited)
+ return 0;
+
+#ifdef CONFIG_USE_OF
+ np = of_find_matching_node(NULL, fh_pmu_match);
+
+ if (np) {
+ fh_pmu_regs = of_iomap(np, 0);
+ } else {
+ pr_err("ERROR: cannot get pmu regs from dts\n");
+ return -1;
+ }
+#else
+ fh_pmu_regs = (void __iomem *)VA_PMU_REG_BASE;
+#endif
+
+ s_pmu_inited = 1;
+ return 0;
+}
diff --git a/arch/arm/mach-fh/soc.h b/arch/arm/mach-fh/soc.h
new file mode 100644
index 00000000..8b5687cd
--- /dev/null
+++ b/arch/arm/mach-fh/soc.h
@@ -0,0 +1,9 @@
+#ifndef _SOC_H_
+#define _SOC_H_
+
+void fh_pmu_set_reg(u32 offset, u32 data);
+u32 fh_pmu_get_reg(u32 offset);
+void fh_pmu_set_reg_m(u32 offset, u32 data, u32 mask);
+int fh_pmu_init(void);
+
+#endif /* _SOC_H_ */
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index f7c74135..f8cc394d 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -63,16 +63,15 @@ pmdval_t user_pmd_table = _PAGE_USER_TABLE;
#define CPOLICY_WRITEALLOC 4
static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
-static unsigned int ecc_mask __initdata = 0;
+static unsigned int ecc_mask __initdata;
pgprot_t pgprot_user;
+EXPORT_SYMBOL(pgprot_user);
pgprot_t pgprot_kernel;
+EXPORT_SYMBOL(pgprot_kernel);
pgprot_t pgprot_hyp_device;
pgprot_t pgprot_s2;
pgprot_t pgprot_s2_device;
-EXPORT_SYMBOL(pgprot_user);
-EXPORT_SYMBOL(pgprot_kernel);
-
struct cachepolicy {
const char policy[16];
unsigned int cr_mask;
@@ -122,7 +121,7 @@ static struct cachepolicy cache_policies[] __initdata = {
};
#ifdef CONFIG_CPU_CP15
-static unsigned long initial_pmd_value __initdata = 0;
+static unsigned long initial_pmd_value __initdata;
/*
* Initialise the cache_policy variable with the initial state specified
@@ -185,6 +184,7 @@ static int __init early_cachepolicy(char *p)
if (selected != cachepolicy) {
unsigned long cr = __clear_cr(cache_policies[selected].cr_mask);
+
cachepolicy = selected;
flush_cache_all();
set_cr(cr);
@@ -196,6 +196,7 @@ early_param("cachepolicy", early_cachepolicy);
static int __init early_nocache(char *__unused)
{
char *p = "buffered";
+
pr_warn("nocache is deprecated; use cachepolicy=%s\n", p);
early_cachepolicy(p);
return 0;
@@ -653,6 +654,7 @@ static void __init build_mem_type_table(void)
for (i = 0; i < 16; i++) {
pteval_t v = pgprot_val(protection_map[i]);
+
protection_map[i] = __pgprot(v | user_pgprot);
}
@@ -690,6 +692,7 @@ static void __init build_mem_type_table(void)
for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
struct mem_type *t = &mem_types[i];
+
if (t->prot_l1)
t->prot_l1 |= PMD_DOMAIN(t->domain);
if (t->prot_sect)
@@ -715,6 +718,7 @@ EXPORT_SYMBOL(phys_mem_access_prot);
static void __init *early_alloc_aligned(unsigned long sz, unsigned long align)
{
void *ptr = __va(memblock_alloc(sz, align));
+
memset(ptr, 0, sz);
return ptr;
}
@@ -739,6 +743,7 @@ static pte_t * __init arm_pte_alloc(pmd_t *pmd, unsigned long addr,
{
if (pmd_none(*pmd)) {
pte_t *pte = alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
+
__pmd_populate(pmd, __pa(pte), prot);
}
BUG_ON(pmd_bad(*pmd));
@@ -758,6 +763,7 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
bool ng)
{
pte_t *pte = arm_pte_alloc(pmd, addr, type->prot_l1, alloc);
+
do {
set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)),
ng ? PTE_EXT_NG : 0);
@@ -974,6 +980,7 @@ void __init create_mapping_late(struct mm_struct *mm, struct map_desc *md,
{
#ifdef CONFIG_ARM_LPAE
pud_t *pud = pud_alloc(mm, pgd_offset(mm, md->virtual), md->virtual);
+
if (WARN_ON(!pud))
return;
pmd_alloc(mm, pud, 0);
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 2ed1b8a9..8a3b96b9 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1006,3 +1006,9 @@ eco5_bx2 MACH_ECO5_BX2 ECO5_BX2 4572
eukrea_cpuimx28sd MACH_EUKREA_CPUIMX28SD EUKREA_CPUIMX28SD 4573
domotab MACH_DOMOTAB DOMOTAB 4574
pfla03 MACH_PFLA03 PFLA03 4575
+fh8856v200 MACH_FH8856V200 FH8856V200 9999
+fh8852v200 MACH_FH8852V200 FH8852V200 9999
+fh8858v200 MACH_FH8858V200 FH8858V200 9999
+fh8856v210 MACH_FH8856V210 FH8856V210 9999
+fh8852v210 MACH_FH8852V210 FH8852V210 9999
+fh8858v210 MACH_FH8858V210 FH8858V210 9999
diff --git a/crypto/Kconfig b/crypto/Kconfig
index ab0d93ab..06e7f810 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1649,7 +1649,7 @@ config CRYPTO_DRBG_CTR
config CRYPTO_DRBG
tristate
- default CRYPTO_DRBG_MENU
+ default n
select CRYPTO_RNG
select CRYPTO_JITTERENTROPY
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 860c9e5d..d35083bb 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -359,6 +359,23 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
return 0;
}
+struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
+ u32 type, u32 mask)
+{
+ struct crypto_tfm *t_crytfm = 0;
+ struct crypto_ablkcipher *tfm = 0;
+ int err;
+
+ t_crytfm = crypto_alloc_base(alg_name, type, mask);
+ if (IS_ERR(t_crytfm)) {
+ pr_err("failed to alloc t_crytfm!\n");
+ err = PTR_ERR(t_crytfm);
+ return err;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ return tfm;
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher);
#ifdef CONFIG_NET
static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
{
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index b5953f1d..d945d992 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -443,6 +443,7 @@ EXPORT_SYMBOL_GPL(af_alg_free_sg);
int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
{
struct cmsghdr *cmsg;
+ struct af_alg_usr_def *p_usr_def;
for_each_cmsghdr(cmsg, msg) {
if (!CMSG_OK(msg, cmsg))
@@ -471,7 +472,12 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con)
return -EINVAL;
con->aead_assoclen = *(u32 *)CMSG_DATA(cmsg);
break;
+ case ALG_USR_DEF:
+ p_usr_def = (struct af_alg_usr_def *)CMSG_DATA(cmsg);
+ memcpy(&con->usr_def, p_usr_def,
+ sizeof(struct af_alg_usr_def));
+ break;
default:
return -EINVAL;
}
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index aaf2f810..4455886e 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -307,6 +307,7 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
struct skcipher_ctx *ctx = ask->private;
struct skcipher_tfm *skc = pask->private;
struct crypto_skcipher *tfm = skc->skcipher;
+ struct af_alg_usr_def *p_usr_def = crypto_skcipher_usr_def(tfm);
unsigned ivsize = crypto_skcipher_ivsize(tfm);
struct skcipher_sg_list *sgl;
struct af_alg_control con = {};
@@ -332,7 +333,8 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
default:
return -EINVAL;
}
-
+ /* cpy usr def msg to tfm.... */
+ memcpy(p_usr_def, &con.usr_def, sizeof(struct af_alg_usr_def));
if (con.iv && con.iv->ivlen != ivsize)
return -EINVAL;
}
@@ -423,7 +425,6 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
ctx->merge = plen & (PAGE_SIZE - 1);
}
-
err = 0;
ctx->more = msg->msg_flags & MSG_MORE;
@@ -665,7 +666,6 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
}
used = min_t(unsigned long, ctx->used, msg_data_left(msg));
-
used = af_alg_make_sg(&ctx->rsgl, &msg->msg_iter, used);
err = used;
if (err < 0)
@@ -704,7 +704,6 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
skcipher_pull_sgl(sk, used, 1);
iov_iter_advance(&msg->msg_iter, used);
}
-
err = 0;
unlock:
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index 93110d70..a3258db5 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -150,21 +150,26 @@ static int skcipher_setkey_ablkcipher(struct crypto_skcipher *tfm,
static int skcipher_crypt_ablkcipher(struct skcipher_request *req,
int (*crypt)(struct ablkcipher_request *))
{
+
+
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct crypto_ablkcipher **ctx = crypto_skcipher_ctx(tfm);
struct ablkcipher_request *subreq = skcipher_request_ctx(req);
+ /* bind to the tfm usr def... and then driver will parse it */
+ subreq->usr_def = crypto_skcipher_usr_def(tfm);
ablkcipher_request_set_tfm(subreq, *ctx);
ablkcipher_request_set_callback(subreq, skcipher_request_flags(req),
req->base.complete, req->base.data);
ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
req->iv);
-
+ /* call aes driver.. */
return crypt(subreq);
}
static int skcipher_encrypt_ablkcipher(struct skcipher_request *req)
{
+
struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
struct crypto_tfm *tfm = crypto_skcipher_tfm(skcipher);
struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index e1e2066c..724edefb 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -88,8 +88,6 @@ source "drivers/regulator/Kconfig"
source "drivers/media/Kconfig"
-source "drivers/video/Kconfig"
-
source "sound/Kconfig"
source "drivers/hid/Kconfig"
@@ -202,4 +200,7 @@ source "drivers/hwtracing/intel_th/Kconfig"
source "drivers/fpga/Kconfig"
+source "drivers/tee/Kconfig"
+
+source "drivers/cryptodev-linux-master/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 7c3d58dc..5039fae4 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -17,7 +17,6 @@ obj-y += pwm/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
-obj-y += video/
obj-y += idle/
# IPMI must come before ACPI in order to provide IPMI opregion support
@@ -34,7 +33,7 @@ obj-y += clk/
# Many drivers will want to use DMA so this has to be made available
# really early.
obj-$(CONFIG_DMADEVICES) += dma/
-
+obj-$(CONFIG_CRYPTODEV) += cryptodev-linux-master/
# SOC specific infrastructure drivers.
obj-y += soc/
@@ -175,3 +174,5 @@ obj-$(CONFIG_STM) += hwtracing/stm/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_NVMEM) += nvmem/
obj-$(CONFIG_FPGA) += fpga/
+obj-$(CONFIG_TEE) += tee/
+
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 81b65d0e..46c9ba13 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1791,10 +1791,10 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
static int maxwarn = 10;
int ret;
- if (!crng_ready() && maxwarn > 0) {
+ if (crng_init == 0 && maxwarn > 0) {
maxwarn--;
if (__ratelimit(&urandom_warning))
- printk(KERN_NOTICE "random: %s: uninitialized "
+ printk_once(KERN_NOTICE "random: %s: uninitialized "
"urandom read (%zd bytes read)\n",
current->comm, nbytes);
spin_lock_irqsave(&primary_crng.lock, flags);
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 42042c0a..722166e5 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -50,6 +50,8 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
# please keep this section sorted lexicographically by directory path name
+ifeq ($(CONFIG_USE_OF),y)
+endif
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
obj-$(CONFIG_ARCH_ARTPEC) += axis/
obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/
diff --git a/drivers/clk/fh/Makefile b/drivers/clk/fh/Makefile
new file mode 100644
index 00000000..d38e9e86
--- /dev/null
+++ b/drivers/clk/fh/Makefile
@@ -0,0 +1,6 @@
+#
+# Fullhan Clock specific Makefile
+#
+ifeq ($(CONFIG_USE_OF),y)
+obj-$(CONFIG_ARCH_FH885xV200) += clk-fh885xv200.o
+endif
diff --git a/drivers/clk/fh/clk-fh885xv200.c b/drivers/clk/fh/clk-fh885xv200.c
new file mode 100644
index 00000000..88fe2df5
--- /dev/null
+++ b/drivers/clk/fh/clk-fh885xv200.c
@@ -0,0 +1,972 @@
+/*
+ * Clock and PLL control for FH devices
+ *
+ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <mach/pmu.h>
+
+static DEFINE_SPINLOCK(clk_lock);
+
+/* Maximum number of parents our clocks have */
+#define FH_MAX_PARENTS 4
+
+#define PROC_FILE "driver/clock"
+
+#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
+
+
+#define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
+#define CLRMASK(len, pos) (~(SETMASK(len, pos)))
+
+#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
+#define FACTOR_SET(bit, len, reg, val) \
+ (((reg) & CLRMASK(len, bit)) | (val << (bit)))
+
+#define CONFIG_ISP_CLK_RATE 240000000
+#define CONFIG_JPEG_CLK_RATE 200000000
+#define CONFIG_VEU_CLK_RATE 300000000
+
+/* init clk base addr */
+void __iomem *base_addr;
+
+/* Matches for pll clocks */
+struct clk_factors {
+ struct clk_hw hw;
+ void __iomem *reg0;
+ void __iomem *reg1;
+ u32 m;
+ u32 n;
+ u32 pr;
+ u32 divcop;
+ spinlock_t *lock;
+};
+
+struct fh_clk_divider {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u32 prediv;
+ u32 div_flag;
+ u32 div_reg_mask;
+ spinlock_t *lock;
+};
+
+struct fh_clk_phase {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u32 mux;
+ spinlock_t *lock;
+};
+
+struct fh_clk_config {
+ char name[32];
+ u32 rate;
+};
+
+
+
+static struct of_device_id clk_fix_match[] __initdata = {
+ {.compatible = "fixed-clock", .data = NULL,},
+ {}
+};
+
+/* Matches for pll clocks */
+static struct of_device_id clk_factors_match[] = {
+ {.compatible = "fh pll-ddr-rclk", .data = NULL,},
+ {.compatible = "fh pll-cpu-pclk", .data = NULL,},
+ {.compatible = "fh pll-cpu-rclk", .data = NULL,},
+ {.compatible = "fh pll-sys-pclk", .data = NULL,},
+ {.compatible = "fh pll-sys-rclk", .data = NULL,},
+ {}
+};
+
+/* Matches for divided outputs */
+static struct of_device_id clk_divs_match[] = {
+ {.compatible = "fh fh-arm-clk", .data = NULL,},
+ {.compatible = "fh fh-arc-clk", .data = NULL,},
+ {.compatible = "fh fh-ahb-clk", .data = NULL,},
+ {.compatible = "fh sysp-div12-clk", .data = NULL,},
+ {.compatible = "fh fh-ddr-clk", .data = NULL,},
+ {.compatible = "fh fh-ispa-clk", .data = NULL,},
+ {.compatible = "fh fh-ispb-clk", .data = NULL,},
+ {.compatible = "fh fh-vpu-clk", .data = NULL,},
+ {.compatible = "fh fh-pix-clk", .data = NULL,},
+ {.compatible = "fh fh-jpeg-clk", .data = NULL,},
+ {.compatible = "fh fh-bgm-clk", .data = NULL,},
+ {.compatible = "fh fh-jpeg-adapt-clk", .data = NULL,},
+ {.compatible = "fh fh-sdc0-clk", .data = NULL,},
+ {.compatible = "fh fh-sdc1-clk", .data = NULL,},
+ {.compatible = "fh fh-spi0-clk", .data = NULL,},
+ {.compatible = "fh fh-spi1-clk", .data = NULL,},
+ {.compatible = "fh fh-spi2-clk", .data = NULL,},
+ {.compatible = "fh fh-veu-clk", .data = NULL,},
+ {.compatible = "fh fh-veu-adapt-clk", .data = NULL,},
+ {.compatible = "fh fh-cis-clk-out", .data = NULL,},
+ {.compatible = "fh fh-ac-mclk", .data = NULL,},
+ {.compatible = "fh fh-usb-clk", .data = NULL,},
+ {.compatible = "fh fh-eth-clk", .data = NULL,},
+ {.compatible = "fh fh-ethrmii-clk", .data = NULL,},
+ {.compatible = "fh fh-uart0-clk", .data = NULL,},
+ {.compatible = "fh fh-uart1-clk", .data = NULL,},
+ {.compatible = "fh fh-uart2-clk", .data = NULL,},
+ {.compatible = "fh fh-i2c0-clk", .data = NULL,},
+ {.compatible = "fh fh-i2c1-clk", .data = NULL,},
+ {.compatible = "fh fh-i2c2-clk", .data = NULL,},
+ {.compatible = "fh fh-pwm-clk", .data = NULL,},
+ {.compatible = "fh fh-pts-clk", .data = NULL,},
+ {.compatible = "fh fh-efuse-clk", .data = NULL,},
+ {.compatible = "fh fh-tmr0-clk", .data = NULL,},
+ {.compatible = "fh fh-ac-clk", .data = NULL,},
+ {.compatible = "fh fh-i2s-clk", .data = NULL,},
+ {.compatible = "fh fh-sadc-clk", .data = NULL,},
+ {.compatible = "fh fh-wdt-clk", .data = NULL,},
+ {.compatible = "fh fh-gpio0-dbclk", .data = NULL,},
+ {.compatible = "fh fh-gpio1-dbclk", .data = NULL,},
+ {.compatible = "fh fh-emc-hclk", .data = NULL,},
+ {.compatible = "fh fh-rtc-pclk", .data = NULL,},
+ {.compatible = "fh fh-aes-hclk", .data = NULL,},
+ {.compatible = "fh fh-mipi-dphy-clk", .data = NULL,},
+ {.compatible = "fh fh-mipi-wrap-clk", .data = NULL,},
+ {.compatible = "fh fh-rtc-hclk", .data = NULL,},
+ {.compatible = "fh fh-emac-hclk", .data = NULL,},
+ {.compatible = "fh fh-usb-clk", .data = NULL,},
+ {.compatible = "fh fh-aes-hclk", .data = NULL,},
+ {.compatible = "fh fh-ephy-clk", .data = NULL,},
+ {.compatible = "fh fh-sdc08x-clk", .data = NULL,},
+ {.compatible = "fh fh-sdc18x-clk", .data = NULL,},
+ {.compatible = "fh fh-mipic-pclk", .data = NULL,},
+ {.compatible = "fh fh-gpio0-pclk", .data = NULL,},
+ {.compatible = "fh fh-gpio1-pclk", .data = NULL,},
+ {.compatible = "fh fh-isp-hclk", .data = NULL,},
+ {.compatible = "fh fh-veu-hclk", .data = NULL,},
+ {.compatible = "fh fh-bgm-hclk", .data = NULL,},
+ {.compatible = "fh fh-adapt-hclk", .data = NULL,},
+ {.compatible = "fh fh-jpg-hclk", .data = NULL,},
+ {.compatible = "fh fh-jpg-adapt-clk", .data = NULL,},
+ {.compatible = "fh fh-vpu-hclk", .data = NULL,},
+ {}
+};
+
+/* Matches for phase clocks */
+
+static struct of_device_id clk_phase_match[] __initdata = {
+ {.compatible = "fh fh-sdc0-clk_sample", .data = NULL,},
+ {.compatible = "fh fh-sdc0-clk_drv", .data = NULL,},
+ {.compatible = "fh fh-sdc1-clk_sample", .data = NULL,},
+ {.compatible = "fh fh-sdc1-clk_drv", .data = NULL,},
+ {}
+};
+
+/* init clocks base*/
+static struct of_device_id clk_init_match[] __initdata = {
+ {.compatible = "fh,fh-clk", .data = NULL,},
+ {}
+};
+
+
+void __init fh_fixed_clk_setup(struct device_node *node,
+ void *name)
+{
+ struct clk *clk;
+ u32 out_values;
+ const char *clk_name;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+ strcpy(name, clk_name);
+ of_property_read_u32_array(node,
+ "clock-frequency", &out_values,
+ 1);
+ clk = clk_register_fixed_rate(NULL, clk_name,
+ NULL,
+ CLK_IS_ROOT,
+ out_values);
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ clk_register_clkdev(clk, clk_name, NULL);
+ }
+}
+#define DIVVCO_ONE_DEVISION 0x0
+#define DIVVCO_TWO_DEVISION 0x8
+#define DIVVCO_FOUR_DEVISION 0xc
+#define DIVVCO_EIGHT_DEVISION 0xd
+#define DIVVCO_SIXTEEN_DEVISION 0xe
+#define DIVVCO_THIRTYTWO_DEVISION 0xf
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ unsigned int m = 0, n = 0, pr = 1;
+ unsigned int clk_vco, divvcop = 1, shift;
+ u32 reg;
+ unsigned long rate;
+ struct clk_factors *factors = to_clk_factors(hw);
+ unsigned int divcop = 0;
+ /* Fetch the register value */
+ reg = readl(factors->reg0);
+ shift = ffs(factors->m)-1;
+ m = (reg&factors->m) >> shift;
+
+ shift = ffs(factors->n)-1;
+ n = (reg&factors->n) >> shift;
+
+ /*pll databook*/
+ if (m < 4)
+ m = 128+m;
+
+ if (m == 0xb)
+ m = 0xa;
+
+ shift = ffs(factors->pr)-1;
+ pr = (reg&factors->pr) >> shift;
+
+ reg = readl(factors->reg1);
+ shift = ffs(factors->divcop)-1;
+ divcop = ((reg&factors->divcop) >> shift);
+
+
+ /* Calculate the rate */
+ switch (divcop){
+ case DIVVCO_ONE_DEVISION:
+ divvcop = 1;
+ break;
+
+ case DIVVCO_TWO_DEVISION:
+ divvcop = 2;
+ break;
+
+ case DIVVCO_FOUR_DEVISION:
+ divvcop = 4;
+ break;
+
+ case DIVVCO_EIGHT_DEVISION:
+ divvcop = 8;
+ break;
+
+ case DIVVCO_SIXTEEN_DEVISION:
+ divvcop = 16;
+ break;
+
+ case DIVVCO_THIRTYTWO_DEVISION:
+ divvcop = 32;
+ break;
+ default:
+ printk("divvcop error:%x\n",divvcop);
+ }
+
+ clk_vco = parent_rate * m / (n+1);
+ rate = clk_vco/ (pr+1)/divvcop;
+ return rate;
+
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+ {
+ unsigned int m = 0, n = 0, pr = 1;
+ unsigned int clk_vco, divvcop = 1, shift;
+ u32 reg;
+ struct clk_factors *factors = to_clk_factors(hw);
+ unsigned int divcop = 0;
+
+ /* Fetch the register value */
+ reg = readl(factors->reg0);
+
+ shift = ffs(factors->m)-1;
+ m = (reg&factors->m) >> shift;
+
+ shift = ffs(factors->n)-1;
+ n = (reg&factors->n) >> shift;
+
+
+ /*pll databook*/
+ if(m < 4)
+ m = 128+m;
+
+ if(m == 0xb)
+ m = 0xa;
+
+ shift = ffs(factors->pr)-1;
+ pr = (reg&factors->pr) >> shift;
+
+ reg = readl(factors->reg1);
+ shift = ffs(factors->divcop)-1;
+ divcop = (reg&factors->divcop) >> shift;
+
+
+ /* Calculate the rate */
+ switch (divcop){
+ case DIVVCO_ONE_DEVISION:
+ divvcop = 1;
+ break;
+
+ case DIVVCO_TWO_DEVISION:
+ divvcop = 2;
+ break;
+
+ case DIVVCO_FOUR_DEVISION:
+ divvcop = 4;
+ break;
+
+ case DIVVCO_EIGHT_DEVISION:
+ divvcop = 8;
+ break;
+
+ case DIVVCO_SIXTEEN_DEVISION:
+ divvcop = 16;
+ break;
+
+ case DIVVCO_THIRTYTWO_DEVISION:
+ divvcop = 32;
+ break;
+ default:
+ printk("divvcop error:%x\n",divvcop);
+ }
+
+ clk_vco = (*parent_rate) * m / (n+1);
+ rate = clk_vco / (pr+1) / divvcop;
+ return rate;
+
+ }
+
+
+static const struct clk_ops clk_pll_ops = {
+ .recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_round_rate,
+};
+
+static unsigned long fh_clk_divide_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ u32 divide = 0;
+ struct fh_clk_divider *factors = (struct fh_clk_divider *)hw;
+ unsigned long rate;
+ unsigned long shift;
+ unsigned long flags = 0;
+
+ if (factors->lock)
+ spin_lock_irqsave(factors->lock, flags);
+ if (factors->div_flag) {
+ /* Fetch the register value */
+ reg = readl(factors->reg);
+
+ /* Get each individual factor if applicable */
+ shift = ffs(factors->div_reg_mask)-1;
+ divide = (factors->div_reg_mask & reg)>> shift;
+
+ /* Calculate the rate */
+ rate = (parent_rate) / (divide+1) / factors->prediv;
+ } else
+ rate = parent_rate / factors->prediv;
+ if (factors->lock)
+ spin_unlock_irqrestore(factors->lock, flags);
+
+ return rate;
+}
+
+static long fh_clk_divide_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u32 reg;
+ u32 rount_rate = 0, divide;
+ struct fh_clk_divider *factors = (struct fh_clk_divider *)hw;
+ unsigned long flags = 0;
+
+ if (factors->lock)
+ spin_lock_irqsave(factors->lock, flags);
+
+ if (factors->div_flag) {
+
+ /* Fetch the register value */
+ reg = readl(factors->reg);
+
+ /* Calculate the rate */
+ divide = (*parent_rate) / factors->prediv / rate;
+ rount_rate = (*parent_rate) / divide / factors->prediv;
+ } else
+ pr_err("fh_clk_divide_round_rate not support divide\n");
+
+ if (factors->lock)
+ spin_unlock_irqrestore(factors->lock, flags);
+
+ return rount_rate;
+}
+
+static int fh_clk_divide_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ u32 reg;
+ struct fh_clk_divider *factors = (struct fh_clk_divider *)hw;
+ u32 divide = 0;
+ unsigned long flags = 0;
+ unsigned long shift = 0;
+
+ if (factors->lock)
+ spin_lock_irqsave(factors->lock, flags);
+
+
+ if (factors->div_flag) {
+
+ /* Fetch the register value */
+ reg = readl(factors->reg);
+
+ divide = parent_rate/rate/factors->prediv - 1;
+ /*printk("fh_clk_divide_set_rate:%x\n",divide);*/
+
+ shift = ffs(factors->div_reg_mask)-1;
+
+
+ reg &= ~(factors->div_reg_mask);
+ reg |= ((divide << shift) & factors->div_reg_mask);
+
+ /* Apply them now */
+ clk_writel(reg, factors->reg);
+
+ }
+ if (factors->lock)
+ spin_unlock_irqrestore(factors->lock, flags);
+
+ return 0;
+}
+
+
+static const struct clk_ops fh_clk_divider_ops = {
+ .recalc_rate = fh_clk_divide_recalc_rate,
+ .round_rate = fh_clk_divide_round_rate,
+ .set_rate = fh_clk_divide_set_rate,
+};
+
+static int __init fh_divs_clk_setup(struct device_node *node,
+ void *name)
+{
+ struct clk *clk;
+ struct clk_gate *gate = NULL;
+ struct clk_hw *clk_mux_hw = NULL;
+ struct clk_mux *mux = NULL;
+ struct clk_hw *clk_gate_hw = NULL;
+ struct clk_hw *clk_divider_hw = NULL;
+ struct fh_clk_divider *fh_divider = NULL;
+ const char *clk_name;
+ const char *parents[FH_MAX_PARENTS];
+ void __iomem *reg = NULL;
+ int i = 0;
+ u32 div_mask = 0;
+ u32 gate_mask = 0;
+ u32 mux_mask = 0;
+ u32 prediv = 0;
+
+ if (!base_addr)
+ return 0;
+
+ /* if we have a mux, we will have >1 parents */
+ while (i < FH_MAX_PARENTS &&
+ (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+
+ fh_divider = kzalloc(sizeof(*fh_divider), GFP_KERNEL);
+ if (!fh_divider)
+ return 0;
+
+ fh_divider->lock = &clk_lock;
+ of_property_read_string(node, "clock-output-names", &clk_name);
+ strcpy(name, clk_name);
+
+ if(!of_property_read_u32(node, "prediv", &prediv)) {
+ fh_divider->prediv = prediv;
+ clk_divider_hw = &fh_divider->hw;
+ } else
+ fh_divider->prediv = 1;
+
+
+ /* Leaves can be fixed or configurable divisors */
+ if (!of_property_read_u32(node, "div", &div_mask)) {
+ reg = of_iomap(node, 0);
+ clk_divider_hw = &fh_divider->hw;
+ fh_divider->reg = reg;
+ fh_divider->div_flag = 1;
+ fh_divider->div_reg_mask= div_mask;
+ }
+
+ /* Add a gate if this factor clock can be gated */
+ if (!of_property_read_u32(node, "gate", &gate_mask)) {
+ gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+ if (!gate) {
+ kfree(fh_divider);
+ return 0;
+ }
+
+ /* set up gate properties */
+ reg = of_iomap(node, 1);
+ gate->reg = reg;
+ gate->bit_idx =ffs(gate_mask)-1;
+ gate->lock = &clk_lock;
+ gate->flags = CLK_GATE_SET_TO_DISABLE;
+ clk_gate_hw = &gate->hw;
+ }
+
+ if (!of_property_read_u32(node, "mux", &mux_mask)) {
+ mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+
+
+ /* set up gate properties */
+ reg = of_iomap(node, 2);
+ mux->reg = reg;
+ mux->shift = ffs(mux_mask)-1;
+ mux->mask = mux_mask>>mux->shift;
+ mux->lock = &clk_lock;
+ clk_mux_hw = &mux->hw;
+ }
+ #if 1
+ clk = clk_register_composite(NULL, clk_name,
+ parents, i,
+ clk_mux_hw, &clk_mux_ops,
+ clk_divider_hw, &fh_clk_divider_ops,
+ clk_gate_hw, &clk_gate_ops, CLK_IGNORE_UNUSED);
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ clk_register_clkdev(clk, clk_name, NULL);
+ }
+ #endif
+ return 1;
+}
+
+
+static int __init fh_pll_clk_setup(struct device_node *node,
+ void *name)
+{
+ struct clk *clk;
+ struct clk_factors *factors;
+ const char *clk_name = node->name;
+ const char *parents[FH_MAX_PARENTS];
+ void __iomem *reg0;
+ void __iomem *reg1;
+ int i = 0;
+ u32 pr = 0;
+ u32 divcop = 0;
+ u32 m = 0;
+ u32 n = 0;
+
+ if (!base_addr)
+ return 0;
+
+ reg0 = of_iomap(node, 0);
+ reg1 = of_iomap(node, 1);
+ /* if we have a mux, we will have >1 parents */
+ while (i < FH_MAX_PARENTS &&
+ (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+ of_property_read_string(node, "clock-output-names", &clk_name);
+ strcpy(name, clk_name);
+ factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+ if (!factors)
+ return 0;
+
+ if (of_property_read_u32(node, "m", &m)) {
+ pr_err("%s:get node attr m error\n", __func__);
+ return -1;
+ }
+ factors->m = m;
+
+ if (of_property_read_u32(node, "n", &n)) {
+ pr_err("%s get node attr n error\n", __func__);
+ return -1;
+ }
+ factors->n = n;
+
+ if (of_property_read_u32(node, "pr", &pr)) {
+ pr_err("%s get node attr pr error\n", __func__);
+ return -1;
+ }
+ factors->pr = pr;
+
+ if (of_property_read_u32(node, "divcop", &divcop)) {
+ pr_err("%s get node attr dicop error\n", __func__);
+ return -1;
+ }
+ factors->divcop = divcop;
+
+ /* set up factors properties */
+ factors->reg0 = reg0;
+ factors->reg1 = reg1;
+ factors->lock = &clk_lock;
+ clk = clk_register_composite(NULL, clk_name,
+ parents, i,
+ NULL, NULL,
+ &factors->hw, &clk_pll_ops,
+ NULL, NULL, CLK_IGNORE_UNUSED);
+ if (!IS_ERR(clk)) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ clk_register_clkdev(clk, clk_name, NULL);
+ }
+ return 1;
+}
+
+
+static int fh_clk_set_phase(struct clk_hw *hw,
+ int degree)
+{
+ u32 reg;
+ struct fh_clk_phase *phase = (struct fh_clk_phase *)hw;
+ unsigned long flags = 0;
+ u32 local_degree = 0;
+ u32 shift = 0;
+
+ /*printk("fh_clk_set_phase:%d\n",degree);*/
+ if (phase->lock)
+ spin_lock_irqsave(phase->lock, flags);
+
+ /* Fetch the register value */
+ reg = readl(phase->reg);
+
+ local_degree = degree;
+
+ shift = ffs(phase->mux)-1;
+
+ reg |= (local_degree << shift);
+
+ /* Apply them now */
+ writel(reg, phase->reg);
+ if (phase->lock)
+ spin_unlock_irqrestore(phase->lock, flags);
+
+ return 1;
+}
+
+static int fh_clk_get_phase(struct clk_hw *hw)
+{
+ u32 reg;
+ struct fh_clk_phase *phase = (struct fh_clk_phase *)hw;
+ unsigned long flags = 0;
+ u32 local_degree = 0;
+ u32 shift;
+
+ if (phase->lock)
+ spin_lock_irqsave(phase->lock, flags);
+
+ /* Fetch the register value */
+ reg = readl(phase->reg);
+ shift = ffs(phase->mux)-1;
+
+ reg = reg&(phase->mux) >> shift;
+ local_degree = reg;
+
+ /*printk("fh_clk_get_phase:%d\n",local_degree);*/
+
+ if (phase->lock)
+ spin_unlock_irqrestore(phase->lock, flags);
+
+ return local_degree;
+}
+
+
+static const struct clk_ops fh_clk_phase_ops = {
+ .set_phase = fh_clk_set_phase,
+ .get_phase = fh_clk_get_phase,
+};
+
+static int __init fh_phase_clk_setup(struct device_node *node,
+ void*data)
+{
+ struct clk *clk;
+ const char *clk_name = node->name;
+ const char *parents[FH_MAX_PARENTS];
+ void __iomem *reg;
+ struct fh_clk_phase *clk_phase = NULL;
+ int i = 0;
+ struct clk_init_data *init = NULL;
+ u32 mux_mask = 0;
+
+ while (i < FH_MAX_PARENTS &&
+ (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+ i++;
+
+ of_property_read_string(node, "clock-output-names", &clk_name);
+
+ if(of_property_read_u32(node, "mux", &mux_mask)) {
+ pr_err("%s get node attr mux error\n", __func__);
+ return -1;
+ }
+
+ clk_phase = kzalloc(sizeof(struct fh_clk_phase), GFP_KERNEL);
+ if (!clk_phase)
+ return 0;
+ clk_phase->mux = mux_mask;
+ init = kzalloc(sizeof(struct clk_init_data), GFP_KERNEL);
+
+ reg = of_iomap(node, 0);
+ /* set up gate properties */
+ clk_phase->reg = reg;
+ clk_phase->lock = &clk_lock;
+ init->ops = &fh_clk_phase_ops;
+ init->parent_names = parents;
+ init->num_parents = i;
+ init->name = clk_name;
+ clk_phase->hw.init = init;
+ clk = clk_register(NULL, &clk_phase->hw);
+
+ if (clk) {
+ of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ clk_register_clkdev(clk, clk_name, NULL);
+ }
+
+ return 1;
+}
+
+
+static void __init of_fh_table_clock_setup(const struct of_device_id *clk_match,
+ void *function)
+{
+ struct device_node *np;
+ const char *name;
+ const struct of_device_id *match;
+ int (*setup_function)(struct device_node *, const void *) = function;
+
+ for_each_matching_node_and_match(np, clk_match, &match) {
+ name = match->name;
+ setup_function(np, name);
+ }
+}
+
+static int __init fh_clk_setup(struct device_node *node,
+ void *data)
+{
+ if (!base_addr)
+ base_addr = of_iomap(node, 0);
+ return 1;
+}
+
+static void __init fh_init_setup(struct fh_clk_config clocks[], int nclocks)
+{
+ int i = 0;
+ /* init clocks base*/
+ of_fh_table_clock_setup(clk_init_match, fh_clk_setup);
+
+ /* Register fixed clocks */
+ of_fh_table_clock_setup(clk_fix_match, fh_fixed_clk_setup);
+
+ /* Register factor clocks */
+ of_fh_table_clock_setup(clk_factors_match, fh_pll_clk_setup);
+
+ /* Register divided output clocks */
+ of_fh_table_clock_setup(clk_divs_match, fh_divs_clk_setup);
+
+ /* Register phase clocks */
+ of_fh_table_clock_setup(clk_phase_match, fh_phase_clk_setup);
+
+ /* Protect the clocks that needs to stay on */
+ for (i = 0; i < nclocks; i++) {
+ struct clk *clk = clk_get(NULL, clocks[i].name);
+
+ if (!IS_ERR(clk)) {
+ clk_set_rate(clk,clocks[i].rate);
+ clk_put(clk);
+ }
+
+ }
+}
+static void del_char(char *str, char ch)
+{
+ char *p = str;
+ char *q = str;
+
+ while (*q) {
+ if (*q != ch)
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+}
+
+static ssize_t fh_clk_proc_write(struct file *filp, const char *buf,
+ size_t len, loff_t *off)
+{
+ int i, ret;
+ char message[64] = {0};
+ char * const delim = ",";
+ char *cur = message;
+ char *param_str[4];
+ unsigned int param[4];
+ struct clk *clk;
+
+ len = (len > 64) ? 64 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for (i = 0; i < 3; i++) {
+ param_str[i] = strsep(&cur, delim);
+ if (!param_str[i]) {
+ pr_err("%s: ERROR: parameter[%d] is empty\n",
+ __func__, i);
+ pr_err("[clk name], [enable/disable], [clk rate]\n");
+ return -EINVAL;
+ }
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ }
+
+ clk = clk_get(NULL, param_str[0]);
+ if (!clk) {
+ pr_err("%s: ERROR: clk %s is not found\n",
+ __func__, param_str[0]);
+ pr_err("[clk name], [enable/disable], [clk rate]\n");
+ return -EINVAL;
+ }
+
+ param[2] = (u32)simple_strtoul(param_str[2], NULL, 10);
+ if (param[2] < 0) {
+ pr_err("ERROR: parameter[2] is incorrect\n");
+ return -EINVAL;
+ }
+
+ if (!strcmp(param_str[1], "enable")) {
+ clk_prepare_enable(clk);
+ pr_err("clk %s enabled\n", param_str[0]);
+ } else if (!strcmp(param_str[1], "disable")) {
+ clk_disable_unprepare(clk);
+ pr_err("clk %s disabled\n", param_str[0]);
+ return len;
+ } else {
+ pr_err("%s: ERROR: parameter[1]:%s is incorrect\n",
+ __func__, param_str[1]);
+ pr_err("[clk name], [enable/disable], [clk rate]\n");
+ return -EINVAL;
+ }
+ ret = clk_set_rate(clk, param[2]);
+ if (ret)
+ pr_err("set clk rate failed\n, ret=%d\n", ret);
+
+ return len;
+}
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter = 0;
+ if (*pos == 0)
+ return &counter;
+ *pos = 0;
+ return NULL;
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ struct of_device_id *match;
+ struct clk *clk = NULL;
+ unsigned long rate;
+ char gate[32];
+
+ seq_printf(sfile, "\nPLL Information:\n");
+ for (match = clk_factors_match; match->name[0]; match++) {
+ clk = clk_get(NULL, match->name);
+ rate = clk_get_rate(clk);
+
+ if (__clk_is_enabled(clk))
+ memcpy(gate, "enable", sizeof("enable"));
+ else
+ memcpy(gate, "disable", sizeof("disable"));
+ seq_printf(sfile, "\t%-20s \t%9luHZ \t%-10s\n",
+ match->name, rate, gate);
+ clk_put(clk);
+ }
+ for (match = clk_divs_match; match->compatible[0]; match++) {
+ if (!match->name[0])
+ continue;
+ clk = NULL;
+ clk = clk_get(NULL, match->name);
+ if (IS_ERR(clk))
+ continue;
+ rate = clk_get_rate(clk);
+
+ if (__clk_is_enabled(clk))
+ memcpy(gate, "enable", sizeof("enable"));
+ else
+ memcpy(gate, "disable", sizeof("disable"));
+ seq_printf(sfile, "\t%-20s \t%9luHZ \t%-10s\n",
+ match->name, rate, gate);
+ clk_put(clk);
+ }
+ return 0;
+}
+
+static const struct seq_operations fh_clk_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+static int fh_clk_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &fh_clk_seq_ops);
+}
+
+static const struct file_operations fh_clk_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_clk_proc_open,
+ .read = seq_read,
+ .write = fh_clk_proc_write,
+ .release = seq_release,
+};
+
+int fh_clk_procfs_init(void)
+{
+ struct proc_dir_entry *proc_file;
+
+ proc_file = proc_create(PROC_FILE, 0644, NULL, &fh_clk_proc_ops);
+ if (!proc_file)
+ pr_err("clock, create proc fs failed\n");
+
+ return 0;
+}
+
+static struct fh_clk_config fh_init_rate_clocks[] __initconst = {
+ {.name = "uart1_clk", .rate = 16666666,},
+ {.name = "uart2_clk", .rate = 16666666,},
+ {.name = "isp_aclk", .rate = CONFIG_ISP_CLK_RATE,},
+ {.name = "veu_clk", .rate = CONFIG_VEU_CLK_RATE,},
+ {.name = "jpeg_clk", .rate = CONFIG_JPEG_CLK_RATE,},
+};
+
+static void __init fh_init_clocks(struct device_node *node)
+{
+ fh_init_setup(fh_init_rate_clocks,
+ ARRAY_SIZE(fh_init_rate_clocks));
+}
+
+CLK_OF_DECLARE(fh_clk_init, "fh,fh-clk", fh_init_clocks);
+module_init(fh_clk_procfs_init);
+
+
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index e2c6e43c..93380bca 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -60,6 +60,16 @@ config DW_APB_TIMER_OF
select DW_APB_TIMER
select CLKSRC_OF
+config FULLHAN_TIMER
+ bool
+
+config FH_SIMPLE_TIMER
+ bool "Fullhan simple timer"
+ default n
+ help
+ Enables Fullhan simple timer.
+
+
config ROCKCHIP_TIMER
bool "Rockchip timer driver" if COMPILE_TEST
depends on ARM || ARM64
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index cf87f407..2ca13034 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -15,6 +15,8 @@ obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
obj-$(CONFIG_DIGICOLOR_TIMER) += timer-digicolor.o
obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
+obj-$(CONFIG_FULLHAN_TIMER) += timer-fh.o
+obj-$(CONFIG_FH_SIMPLE_TIMER) += fh_simple_timer.o
obj-$(CONFIG_ROCKCHIP_TIMER) += rockchip_timer.o
obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o
obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index a2503db7..38131d0b 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -465,9 +465,13 @@ static u32 check_ppi_trigger(int irq)
u32 flags = irq_get_trigger_type(irq);
if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
+#if defined(CONFIG_ARCH_FULLHAN) && !defined(CONFIG_USE_OF)
+ flags = IRQF_TRIGGER_HIGH;
+#else
pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
pr_warn("WARNING: Please fix your firmware\n");
flags = IRQF_TRIGGER_LOW;
+#endif
}
return flags;
@@ -870,12 +874,32 @@ static int __init arch_timer_init(void)
ret = arch_timer_common_init();
if (ret)
return ret;
-
arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI];
return 0;
}
+#if defined(CONFIG_ARCH_FULLHAN) && !defined(CONFIG_USE_OF)
+int arch_timer_noof_init(
+ u32 freq, u32 ppilist[4], int alwayson, int suspendstop)
+{
+ int i;
+
+ arch_timer_rate = freq;
+ arch_timers_present |= ARCH_CP15_TIMER;
+ for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) {
+ arch_timer_ppi[i] = irq_create_mapping(NULL,
+ ppilist[i]);
+ }
+
+ arch_timer_c3stop = alwayson;
+ arch_timer_uses_ppi = PHYS_SECURE_PPI;
+ arch_counter_suspend_stop = suspendstop;
+ arch_timer_init();
+ return 0;
+
+}
+#endif
static int __init arch_timer_of_init(struct device_node *np)
{
int i;
diff --git a/drivers/clocksource/fh_simple_timer.c b/drivers/clocksource/fh_simple_timer.c
new file mode 100644
index 00000000..d44e3ebc
--- /dev/null
+++ b/drivers/clocksource/fh_simple_timer.c
@@ -0,0 +1,259 @@
+#include <linux/module.h>
+#include <linux/fh_simple_timer.h>
+
+//#define FH_TIMER_DEBUG
+#ifdef FH_TIMER_DEBUG
+#define PRINT_DBG(fmt,args...) printk(fmt,##args)
+#else
+#define PRINT_DBG(fmt,args...) do{} while(0)
+#endif
+
+static unsigned int stmr_regbase = 0;
+static unsigned int stmr_clkbase = 0;
+
+
+static inline unsigned int timern_base(int n)
+{
+ unsigned int base = 0;
+ switch (n) {
+ case 0:
+ default:
+ base = stmr_regbase;
+ break;
+ case 1:
+ base = stmr_regbase + 0x14;
+ break;
+ case 2:
+ base = stmr_regbase + 0x28;
+ break;
+ case 3:
+ base = stmr_regbase + 0x3c;
+ break;
+ }
+ return base;
+}
+
+#define TIMERN_REG_BASE(n) (timern_base(n))
+
+#define REG_TIMER_LOADCNT(n) (timern_base(n) + 0x00)
+#define REG_TIMER_CUR_VAL(n) (timern_base(n) + 0x04)
+#define REG_TIMER_CTRL_REG(n) (timern_base(n) + 0x08)
+#define REG_TIMER_EOI_REG(n) (timern_base(n) + 0x0C)
+#define REG_TIMER_INTSTATUS(n) (timern_base(n) + 0x10)
+
+
+
+
+
+
+enum SIMPLE_TIMER_WORKMODE {
+ SIMPLE_TIMER_SEQ,
+ SIMPLE_TIMER_PERIOD
+};
+
+struct simple_time_base
+{
+ struct timerqueue_head simple_timer_queue;
+ int state;
+ int workmode;
+};
+struct fh_simple_timer periodic_timer;
+
+
+static struct simple_time_base base;
+
+static void fh_timer_enable(void)
+{
+ SET_REG((REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x3);
+}
+
+static void fh_timer_disable(void)
+{
+ SET_REG((REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x0);
+}
+
+static void fh_timer_clearirq(void)
+{
+ GET_REG((REG_TIMER_EOI_REG(SIMPLE_TIMER_BASE)));
+}
+
+void fh_simple_timer_set_next(long cycles)
+{
+ int sync_cnt = 0;
+
+ PRINT_DBG("cycles: %lu\n", cycles);
+ cycles *= stmr_clkbase;
+
+ if (cycles < 0) {
+ pr_err("ERROR: cycles is invaild: %lu\n", cycles);
+ fh_timer_clearirq();
+ fh_timer_disable();
+ base.state = SIMPLE_TIMER_ERROR;
+ return;
+ }
+
+ SET_REG_M((REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x00, 0x1);
+ /* zy/ticket/100 : update apb Timer LOADCNT */
+ /* CURRENTVALE could,t be start from new LOADCOUNT */
+ /* cause is timer clk 1M hz and apb is 150M hz */
+ /* check current cnt for it is disabled */
+ while (GET_REG((REG_TIMER_CUR_VAL(SIMPLE_TIMER_BASE))) != 0) {
+ sync_cnt++;
+ if (sync_cnt >= 50) {
+ /* typical cnt is 5 when in 1M timer clk */
+ /* so here use 50 to check whether it is err */
+ pr_err("timer problem,can't disable");
+ }
+ }
+ SET_REG((REG_TIMER_LOADCNT(SIMPLE_TIMER_BASE)), cycles);
+ SET_REG_M((REG_TIMER_CTRL_REG(SIMPLE_TIMER_BASE)), 0x01, 0x1);
+
+}
+
+int fh_simple_timer_create(struct fh_simple_timer* new)
+{
+ timerqueue_init(&new->node);
+ new->node.expires = new->it_value;
+ timerqueue_add(&base.simple_timer_queue, &new->node);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fh_simple_timer_create);
+
+int fh_timer_start(void)
+{
+ struct fh_simple_timer *timer = NULL;
+ struct timerqueue_node *node;
+
+ if (base.state == SIMPLE_TIMER_START)
+ return 0;
+
+
+ node = timerqueue_getnext(&base.simple_timer_queue);
+
+ if(node == NULL)
+ {
+ pr_err("ERROR: timequeue is empty\n");
+ return -1;
+ }
+ base.workmode = SIMPLE_TIMER_SEQ;
+ timer = container_of(node, struct fh_simple_timer, node);
+
+ base.state = SIMPLE_TIMER_START;
+ fh_timer_enable();
+ fh_simple_timer_set_next(ktime_to_us(ktime_sub(timer->it_value, timer->it_delay)));
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fh_timer_start);
+
+int fh_simple_timer_interrupt_seq(void)
+{
+ ktime_t diff;
+ struct fh_simple_timer *curr = NULL, *next = NULL;
+ struct timerqueue_node *node;
+
+ node = timerqueue_getnext(&base.simple_timer_queue);
+
+ if(node == NULL)
+ {
+ pr_err("ERROR: timequeue is empty\n");
+ fh_timer_clearirq();
+ fh_timer_disable();
+ base.state = SIMPLE_TIMER_ERROR;
+ return -1;
+ }
+
+ curr = container_of(node, struct fh_simple_timer, node);
+
+ timerqueue_del(&base.simple_timer_queue, &curr->node);
+
+ curr->function(curr->param);
+
+ node = timerqueue_getnext(&base.simple_timer_queue);
+
+ if(node == NULL)
+ {
+ PRINT_DBG("finished all timers, close device\n");
+ fh_timer_clearirq();
+ fh_timer_disable();
+ base.state = SIMPLE_TIMER_STOP;
+ return 0;
+ }
+
+ next = container_of(node, struct fh_simple_timer, node);
+
+ PRINT_DBG("sec: %lu, nsec: %lu\n",
+ ktime_to_timespec(next->it_value).tv_sec,
+ ktime_to_timespec(next->it_value).tv_nsec);
+
+ diff = ktime_sub(next->it_value, curr->it_value);
+
+ fh_simple_timer_set_next(ktime_to_us(ktime_sub(diff, next->it_delay)));
+ fh_timer_clearirq();
+ return 0;
+}
+int fh_simple_timer_interrupt_period(void)
+{
+
+ periodic_timer.function(periodic_timer.param);
+ fh_timer_clearirq();
+ return 0;
+}
+
+int fh_simple_timer_interrupt(void)
+{
+ if (base.workmode == SIMPLE_TIMER_SEQ)
+ return fh_simple_timer_interrupt_seq();
+ else
+ return fh_simple_timer_interrupt_period();
+}
+
+
+int fh_simple_timer_init(unsigned int regbase,unsigned int clkbase)
+{
+ base.state = SIMPLE_TIMER_STOP;
+ stmr_regbase = regbase;
+ if (clkbase % 1000000 != 0 || clkbase < 1000000) {
+ pr_err("simple timer clk not support %u\n",clkbase);
+ stmr_clkbase = 1;
+ } else {
+ stmr_clkbase = clkbase/1000000;
+ }
+ timerqueue_init_head(&base.simple_timer_queue);
+ memset(&periodic_timer, 0, sizeof(periodic_timer));
+ fh_timer_disable();
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fh_simple_timer_init);
+
+
+int fh_simple_timer_periodic_start(struct fh_simple_timer *tim)
+{
+
+ if (base.state == SIMPLE_TIMER_START)
+ return 0;
+
+ if (tim == NULL)
+ return 0;
+
+ periodic_timer = *tim;
+
+
+
+ base.state = SIMPLE_TIMER_START;
+ base.workmode = SIMPLE_TIMER_PERIOD;
+ fh_timer_enable();
+ fh_simple_timer_set_next(ktime_to_us(ktime_sub(periodic_timer.it_value,
+ periodic_timer.it_delay)));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fh_simple_timer_periodic_start);
+int fh_simple_timer_periodic_stop(void)
+{
+ fh_timer_disable();
+ base.state = SIMPLE_TIMER_STOP;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fh_simple_timer_periodic_stop);
+
diff --git a/drivers/clocksource/timer-fh.c b/drivers/clocksource/timer-fh.c
new file mode 100644
index 00000000..109b2986
--- /dev/null
+++ b/drivers/clocksource/timer-fh.c
@@ -0,0 +1,771 @@
+/*
+ * FH timer subsystem
+ *
+ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/cpumask.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/sched_clock.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/fh_simple_timer.h>
+
+
+static struct clocksource *g_cs;
+
+#ifdef CONFIG_ARCH_FH865x
+#define TMR_CLK (50000000)
+#else
+#define TMR_CLK (1000000)
+#endif
+
+
+#define OFFSET_TIMER_LOADCNT (0x00)
+#define OFFSET_TIMER_CUR_VAL (0x04)
+#define OFFSET_TIMER_CTRL_REG (0x08)
+#define OFFSET_TIMER_EOI_REG (0x0C)
+#define OFFSET_TIMER_INTSTATUS (0x10)
+
+#define OFFSET_TIMERS_INTSTATUS (0xa0)
+
+#define TMR_CONTROL_ENABLE (1 << 0)
+/* 1: periodic, 0:free running. */
+#define TMR_CONTROL_MODE_PERIODIC (1 << 1)
+#define TMR_CONTROL_INT (1 << 2)
+
+struct fh_timer {
+ void __iomem *base;
+ unsigned long freq;
+ int irq;
+};
+
+struct fh_timer_clock_event_device {
+ struct clock_event_device ced;
+ struct fh_timer timer;
+ struct irqaction irqaction;
+ void (*eoi)(struct fh_timer *);
+};
+
+struct fh_timer_clocksource {
+ struct fh_timer timer;
+ struct clocksource cs;
+};
+
+
+
+
+#if defined(CONFIG_SMP)
+struct clock_event_device fh_bc_tmrevt;
+#endif
+
+static inline struct fh_timer_clock_event_device *
+ced_to_fh_timer_ced(struct clock_event_device *evt)
+{
+ return container_of(evt, struct fh_timer_clock_event_device, ced);
+}
+
+static inline struct fh_timer_clocksource *
+clocksource_to_fh_timer_clocksource(struct clocksource *cs)
+{
+ return container_of(cs, struct fh_timer_clocksource, cs);
+}
+
+/**
+ * fh_timer_clocksource_read() - read the current value of a clocksource.
+ *
+ * @fh_cs: The clocksource to read.
+ */
+cycle_t fh_timer_clocksource_read(struct fh_timer_clocksource *fh_cs)
+{
+ return (cycle_t)~(readl(fh_cs->timer.base + OFFSET_TIMER_CUR_VAL));
+}
+
+static cycle_t fh_timer_read_clocksource(struct clocksource *cs)
+{
+ unsigned long current_count;
+ struct fh_timer_clocksource *fh_cs =
+ clocksource_to_fh_timer_clocksource(cs);
+
+ current_count = ~(readl(fh_cs->timer.base + OFFSET_TIMER_CUR_VAL));
+
+ return current_count;
+}
+
+/**
+ * fh_timer_clocksource_start() - start the clocksource counting.
+ *
+ * @fh_cs: The clocksource to start.
+ *
+ * This is used to start the clocksource before registration and can be used
+ * to enable calibration of timers.
+ */
+void fh_timer_clocksource_start(struct fh_timer_clocksource *fh_cs)
+{
+ /*
+ * start count down from 0xffff_ffff. this is done by toggling the
+ * enable bit then load initial load count to ~0.
+ */
+ unsigned long ctrl = readl(fh_cs->timer.base + OFFSET_TIMER_CTRL_REG);
+
+ ctrl &= ~TMR_CONTROL_ENABLE;
+ writel(ctrl, fh_cs->timer.base + OFFSET_TIMER_CTRL_REG);
+ writel(~0, fh_cs->timer.base + OFFSET_TIMER_LOADCNT);
+ /* enable, mask interrupt */
+ ctrl &= ~TMR_CONTROL_MODE_PERIODIC;
+ ctrl |= (TMR_CONTROL_ENABLE | TMR_CONTROL_INT);
+ writel(ctrl, fh_cs->timer.base + OFFSET_TIMER_CTRL_REG);
+ /* read it once to get cached counter value initialized */
+ fh_timer_clocksource_read(fh_cs);
+}
+
+void fh_timer_clock_start(struct fh_timer *timer)
+{
+ /*
+ * start count down from 0xffff_ffff. this is done by toggling the
+ * enable bit then load initial load count to ~0.
+ */
+ unsigned long ctrl = readl(timer->base + OFFSET_TIMER_CTRL_REG);
+
+ ctrl &= ~TMR_CONTROL_ENABLE;
+ writel(ctrl, timer->base + OFFSET_TIMER_CTRL_REG);
+ writel(~0, timer->base + OFFSET_TIMER_LOADCNT);
+ /* enable, mask interrupt */
+ ctrl &= ~TMR_CONTROL_MODE_PERIODIC;
+ ctrl |= (TMR_CONTROL_ENABLE | TMR_CONTROL_INT);
+ writel(ctrl, timer->base + OFFSET_TIMER_CTRL_REG);
+ /* read it once to get cached counter value initialized */
+ readl(timer->base + OFFSET_TIMER_CUR_VAL);
+}
+
+static void fh_timer_restart_clocksource(struct clocksource *cs)
+{
+ struct fh_timer_clocksource *fh_cs =
+ clocksource_to_fh_timer_clocksource(cs);
+
+ fh_timer_clocksource_start(fh_cs);
+}
+
+static void __init timer_get_base_and_rate(struct device_node *np,
+ int type, void __iomem **base, u32 *rate)
+{
+ struct clk *timer_clk;
+#ifdef CONFIG_USE_OF
+ *base = of_iomap(np, 0);
+
+ if (!*base)
+ pr_err("Unable to map regs for %s", np->name);
+
+ timer_clk = clk_get(NULL, "tmr0_clk");
+
+
+ if (!of_property_read_u32(np, "clock-frequency", rate)) {
+ if (!IS_ERR(timer_clk)) {
+ clk_set_rate(timer_clk, *rate);
+ clk_prepare_enable(timer_clk);
+ } else {
+ pr_err("No clock for %s", np->name);
+ }
+ } else {
+ pr_err(" No clock-frequency property for %s", np->name);
+ *rate = 0;
+ }
+#else
+ timer_clk = clk_get(NULL, "tmr0_clk");
+ if (!IS_ERR(timer_clk)) {
+ *rate = TMR_CLK;
+ clk_set_rate(timer_clk, *rate);
+ clk_prepare_enable(timer_clk);
+ } else
+ *rate = 1000000;
+
+ if (type == 1)
+ *base = (void __iomem *)(((unsigned int)*base)+0x14);
+
+#endif
+
+}
+
+static void fh_timer_eoi(struct fh_timer *timer)
+{
+#ifdef CONFIG_ARM_FULLHAN_CPUIDLE
+ extern void fhca7_wakeup_cpu(unsigned int cpu);
+ fhca7_wakeup_cpu(1);
+#endif
+ readl(timer->base + OFFSET_TIMER_EOI_REG);
+}
+
+static irqreturn_t fh_timer_clockevent_irq(int irq, void *data)
+{
+ struct clock_event_device *evt = data;
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+#ifdef CONFIG_FH_SIMPLE_TIMER
+ unsigned int status =
+ readl(fh_ced->timer.base + OFFSET_TIMERS_INTSTATUS);
+
+ if (status & (1 << SIMPLE_TIMER_BASE))
+ fh_simple_timer_interrupt();
+#endif
+
+
+ if (!evt->event_handler) {
+ pr_info("Spurious FH timer interrupt %d", irq);
+ return IRQ_NONE;
+ }
+
+ if (fh_ced->eoi)
+ fh_ced->eoi(&fh_ced->timer);
+
+ evt->event_handler(evt);
+#if defined(CONFIG_SMP)
+ if (fh_bc_tmrevt.broadcast != NULL)
+ fh_bc_tmrevt.broadcast(fh_bc_tmrevt.cpumask);
+
+#endif
+ return IRQ_HANDLED;
+}
+static irqreturn_t fh_bc_timer_clockevent_irq(int irq, void *data)
+{
+ struct clock_event_device *evt = data;
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+ if (!evt->event_handler) {
+ pr_info("Spurious FH bc timer interrupt %d", irq);
+ return IRQ_NONE;
+ }
+
+ if (fh_ced->eoi)
+ fh_ced->eoi(&fh_ced->timer);
+
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+}
+
+
+
+
+static void fh_timer_enable_int(struct fh_timer *timer)
+{
+ unsigned long ctrl = readl(timer->base + OFFSET_TIMER_CTRL_REG);
+ /* clear pending intr */
+ readl(timer->base + OFFSET_TIMER_EOI_REG);
+ ctrl &= ~TMR_CONTROL_INT;
+ writel(ctrl, timer->base + OFFSET_TIMER_CTRL_REG);
+}
+
+static int fh_timer_set_periodic(struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ unsigned long period;
+ int sync_cnt = 0;
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+ period = DIV_ROUND_UP(fh_ced->timer.freq, HZ);
+ ctrl = readl(fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ ctrl |= TMR_CONTROL_MODE_PERIODIC;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ /*
+ * DW APB p. 46, have to disable timer before load counter,
+ * may cause sync problem.
+ */
+ ctrl &= ~TMR_CONTROL_ENABLE;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ while (readl(fh_ced->timer.base + OFFSET_TIMER_CUR_VAL) != 0) {
+ sync_cnt++;
+ if (sync_cnt >= 50) {
+ /* typical cnt is 5 when in 1M timer clk */
+ /* so here use 50 to check whether it is err */
+ pr_err("timer problem,can't disable");
+ }
+ }
+ pr_debug("Setting clock period %lu for HZ %d\n", period, HZ);
+ writel(period, fh_ced->timer.base + OFFSET_TIMER_LOADCNT);
+ ctrl |= TMR_CONTROL_ENABLE;
+ ctrl &= ~TMR_CONTROL_INT;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ return 0;
+}
+static int fh_timer_set_oneshot(struct clock_event_device *evt)
+{
+#if 0
+ unsigned long ctrl;
+ unsigned long period;
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+
+ ctrl = readl(fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ /*
+ * set free running mode, this mode will let timer reload max
+ * timeout which will give time (3min on 25MHz clock) to rearm
+ * the next event, therefore emulate the one-shot mode.
+ */
+ ctrl &= ~TMR_CONTROL_ENABLE;
+ ctrl &= ~TMR_CONTROL_MODE_PERIODIC;
+
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ /* write again to set free running mode */
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+
+ /*
+ * DW APB p. 46, load counter with all 1s before starting free
+ * running mode.
+ */
+ writel(~0, fh_ced->timer.base + OFFSET_TIMER_LOADCNT);
+ ctrl &= ~TMR_CONTROL_INT;
+ ctrl |= TMR_CONTROL_ENABLE;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+#endif
+ return 0;
+}
+
+static int fh_timer_set_oneshot_stopped(struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+ ctrl = readl(fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ ctrl &= ~TMR_CONTROL_ENABLE;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ return 0;
+}
+
+static int fh_timer_set_shutdown(struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+ ctrl = readl(fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ ctrl &= ~TMR_CONTROL_ENABLE;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ return 0;
+}
+
+static int fh_timer_tick_resume(struct clock_event_device *evt)
+{
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+ fh_timer_enable_int(&fh_ced->timer);
+ return 0;
+}
+
+
+
+static int fh_timer_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ int sync_cnt = 0;
+ struct fh_timer_clock_event_device *fh_ced = ced_to_fh_timer_ced(evt);
+
+ /* Disable timer */
+ ctrl = readl(fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ ctrl &= ~TMR_CONTROL_ENABLE;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ /* zy/ticket/100 : update apb Timer LOADCNT */
+ /* CURRENTVALE could,t be start from new LOADCOUNT */
+ /* cause is timer clk 1M hz and apb is 150M hz */
+ /* keep disable for 3us to ensure timer detect it */
+ while (readl(fh_ced->timer.base + OFFSET_TIMER_CUR_VAL) != 0) {
+ sync_cnt++;
+ if (sync_cnt >= 50) {
+ /* typical cnt is 5 when in 1M timer clk */
+ /* so here use 50 to check whether it is err */
+ pr_err("timer problem,can't disable");
+ }
+ }
+ /* write new count */
+ writel(delta, fh_ced->timer.base + OFFSET_TIMER_LOADCNT);
+ ctrl |= TMR_CONTROL_ENABLE;
+ writel(ctrl, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+
+ return 0;
+}
+
+
+/**
+ * fh_timer_clockevent_init() - use an fh timer as a clock_event_device
+ *
+ * @cpu: The CPU the events will be targeted at.
+ * @name: The name used for the timer and the IRQ for it.
+ * @rating: The rating to give the timer.
+ * @base: I/O base for the timer registers.
+ * @irq: The interrupt number to use for the timer.
+ * @freq: The frequency that the timer counts at.
+ *
+ * This creates a clock_event_device for using with the generic clock layer
+ * but does not start and register it. This should be done with
+ * fh_timer_clockevent_register() as the next step. If this is the first time
+ * it has been called for a timer then the IRQ will be requested, if not it
+ * just be enabled to allow CPU hotplug to avoid repeatedly requesting and
+ * releasing the IRQ.
+ */
+struct fh_timer_clock_event_device *
+fh_timer_clockevent_init(int cpu, const char *name, unsigned int rating,
+ void __iomem *base, int irq, unsigned long freq)
+{
+ struct fh_timer_clock_event_device *fh_ced =
+ kzalloc(sizeof(*fh_ced), GFP_KERNEL);
+ int err;
+
+ if (!fh_ced)
+ return NULL;
+
+ fh_ced->timer.base = base;
+ fh_ced->timer.irq = irq;
+ fh_ced->timer.freq = freq;
+ /* TODO: maxsec == 4 ? */
+ clockevents_calc_mult_shift(&fh_ced->ced, freq, 4);
+ fh_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff,
+ &fh_ced->ced);
+ fh_ced->ced.min_delta_ns = clockevent_delta2ns(0xf, &fh_ced->ced);
+ fh_ced->ced.cpumask = cpumask_of(cpu);
+ fh_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ fh_ced->ced.set_state_periodic = fh_timer_set_periodic;
+ fh_ced->ced.set_state_oneshot = fh_timer_set_oneshot;
+ fh_ced->ced.set_state_oneshot_stopped = fh_timer_set_oneshot_stopped;
+ fh_ced->ced.set_state_shutdown = fh_timer_set_shutdown;
+ fh_ced->ced.tick_resume = fh_timer_tick_resume;
+
+
+
+ fh_ced->ced.set_next_event = fh_timer_next_event;
+ fh_ced->ced.irq = fh_ced->timer.irq;
+ fh_ced->ced.rating = rating;
+ fh_ced->ced.name = name;
+
+ fh_ced->irqaction.name = fh_ced->ced.name;
+ fh_ced->irqaction.handler = fh_timer_clockevent_irq;
+ fh_ced->irqaction.dev_id = &fh_ced->ced;
+ fh_ced->irqaction.irq = irq;
+ fh_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL |
+ IRQF_NOBALANCING;
+
+ fh_ced->eoi = fh_timer_eoi;
+
+ err = setup_irq(irq, &fh_ced->irqaction);
+ if (err) {
+ pr_err("failed to request timer irq\n");
+ kfree(fh_ced);
+ fh_ced = NULL;
+ }
+
+ return fh_ced;
+}
+
+struct fh_timer_clock_event_device *
+fh_timer_bc_clockevent_init(int cpu, const char *name, unsigned int rating,
+ void __iomem *base, int irq, unsigned long freq)
+{
+ struct fh_timer_clock_event_device *fh_ced =
+ kzalloc(sizeof(*fh_ced), GFP_KERNEL);
+ int err;
+
+ if (!fh_ced)
+ return NULL;
+
+ fh_ced->timer.base = base;
+ fh_ced->timer.irq = irq;
+ fh_ced->timer.freq = freq;
+ /* TODO: maxsec == 4 ? */
+ clockevents_calc_mult_shift(&fh_ced->ced, freq, 4);
+ fh_ced->ced.max_delta_ns = clockevent_delta2ns(0x7fffffff,
+ &fh_ced->ced);
+ fh_ced->ced.min_delta_ns = clockevent_delta2ns(0xf, &fh_ced->ced);
+ fh_ced->ced.cpumask = cpu_all_mask;
+ fh_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ fh_ced->ced.set_state_periodic = fh_timer_set_periodic;
+ fh_ced->ced.set_state_oneshot = fh_timer_set_oneshot;
+ fh_ced->ced.set_state_oneshot_stopped = fh_timer_set_oneshot_stopped;
+ fh_ced->ced.set_state_shutdown = fh_timer_set_shutdown;
+ fh_ced->ced.tick_resume = fh_timer_tick_resume;
+
+
+
+ fh_ced->ced.set_next_event = fh_timer_next_event;
+ fh_ced->ced.irq = fh_ced->timer.irq;
+ fh_ced->ced.rating = rating;
+ fh_ced->ced.name = "fh_bc_timer";
+
+ fh_ced->irqaction.name = fh_ced->ced.name;
+ fh_ced->irqaction.handler = fh_bc_timer_clockevent_irq;
+ fh_ced->irqaction.dev_id = &fh_ced->ced;
+ fh_ced->irqaction.irq = irq;
+ fh_ced->irqaction.flags = IRQF_TIMER | IRQF_IRQPOLL |
+ IRQF_NOBALANCING;
+
+
+
+ fh_ced->eoi = fh_timer_eoi;
+
+ err = setup_irq(irq, &fh_ced->irqaction);
+ if (err) {
+ pr_err("failed to request timer irq\n");
+ kfree(fh_ced);
+ fh_ced = NULL;
+ }
+
+ return fh_ced;
+}
+
+static unsigned long fh_read_current_timer(void)
+{
+ return g_cs->read(g_cs);
+}
+
+static struct delay_timer fh_delay_timer = {
+ .read_current_timer = fh_read_current_timer,
+};
+
+/**
+ * fh_timer_clocksource_init() - use an fh timer as a clocksource.
+ *
+ * @rating: The rating to give the clocksource.
+ * @name: The name for the clocksource.
+ * @base: The I/O base for the timer registers.
+ * @freq: The frequency that the timer counts at.
+ *
+ * This creates a clocksource using an APB timer but does not yet register it
+ * with the clocksource system. This should be done with
+ * fh_timer_clocksource_register() as the next step.
+ */
+struct fh_timer_clocksource *
+fh_timer_clocksource_init(unsigned int rating, const char *name,
+ void __iomem *base, unsigned long freq)
+{
+ struct fh_timer_clocksource *fh_cs =
+ kzalloc(sizeof(*fh_cs), GFP_KERNEL);
+
+ if (!fh_cs)
+ return NULL;
+
+ fh_cs->timer.base = base;
+ fh_cs->timer.freq = freq;
+ fh_cs->cs.name = name;
+ fh_cs->cs.rating = rating;
+ fh_cs->cs.read = fh_timer_read_clocksource;
+ fh_cs->cs.mask = CLOCKSOURCE_MASK(32);
+ fh_cs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+ fh_cs->cs.resume = fh_timer_restart_clocksource;
+
+ g_cs = &fh_cs->cs;
+
+ fh_delay_timer.freq = freq;
+ register_current_timer_delay(&fh_delay_timer);
+
+ return fh_cs;
+}
+/**
+ * fh_timer_clockevent_register() - register the clock with the generic layer
+ *
+ * @fh_ced: The fh clock to register as a clock_event_device.
+ */
+void fh_timer_clockevent_register(struct fh_timer_clock_event_device *fh_ced)
+{
+#if defined(CONFIG_SMP)
+ int cpu = 0;
+ static struct cpumask bcmask;
+#endif
+ writel(0, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ clockevents_register_device(&fh_ced->ced);
+ fh_timer_enable_int(&fh_ced->timer);
+
+#if defined(CONFIG_SMP)
+ for_each_cpu(cpu, cpu_all_mask) {
+ if (cpu != 0)
+ cpumask_set_cpu(cpu, &bcmask);
+ }
+ /* register broadcast evt */
+ fh_bc_tmrevt.name = "fh_broadcast_timer";
+ fh_bc_tmrevt.cpumask = &bcmask;
+ fh_bc_tmrevt.rating = 300;
+ fh_bc_tmrevt.broadcast = tick_broadcast;
+ clockevents_register_device(&fh_bc_tmrevt);
+#endif
+}
+void fh_bc_timer_clockevent_register(struct fh_timer_clock_event_device *fh_ced)
+{
+ writel(0, fh_ced->timer.base + OFFSET_TIMER_CTRL_REG);
+ clockevents_register_device(&fh_ced->ced);
+ fh_timer_enable_int(&fh_ced->timer);
+
+}
+
+
+/**
+ * fh_timer_clocksource_register() - register the fh clocksource.
+ *
+ * @fh_cs: The clocksource to register.
+ */
+void fh_timer_clocksource_register(struct fh_timer_clocksource *fh_cs)
+{
+ clocksource_register_hz(&fh_cs->cs, fh_cs->timer.freq);
+}
+
+void __init add_clockevent(struct device_node *event_timer,
+ unsigned int iovbase, unsigned int irqno)
+{
+ void __iomem *iobase = (void __iomem *)iovbase;
+ struct fh_timer_clock_event_device *ced;
+ u32 irq, rate;
+ const char *name = "timer0";
+ irq = irq_of_parse_and_map(event_timer, 0);
+ if (irq == 0) /* no use_of */
+ irq = irq_create_mapping(NULL, irqno);
+
+ if (irq == 0)
+ panic("No IRQ for clock event timer");
+
+ if (event_timer != NULL)
+ name = event_timer->name;
+
+ timer_get_base_and_rate(event_timer, 0, &iobase, &rate);
+ ced = fh_timer_clockevent_init(0, name, 300, iobase, irq,
+ rate);
+#ifdef CONFIG_FH_SIMPLE_TIMER
+ fh_simple_timer_init((unsigned int)iobase, rate);
+#endif
+
+
+ if (!ced)
+ panic("Unable to initialise clockevent device");
+
+ fh_timer_clockevent_register(ced);
+}
+
+static void clk_event_handle(struct clock_event_device *evt)
+{
+}
+
+void __init add_bc_clockevent(struct device_node *event_timer,
+ unsigned int iovbase, unsigned int irqno)
+{
+ void __iomem *iobase = (void __iomem *)iovbase;
+ struct fh_timer_clock_event_device *ced;
+ u32 irq, rate;
+ const char *name = "timer0";
+
+ irq = irq_of_parse_and_map(event_timer, 0);
+ if (irq == 0) /* no use_of */
+ irq = irq_create_mapping(NULL, irqno);
+
+
+ if (irq == 0)
+ panic("No IRQ for clock event timer");
+
+ timer_get_base_and_rate(event_timer, 0, &iobase, &rate);
+ if (event_timer != NULL)
+ name = event_timer->name;
+
+
+ ced = fh_timer_bc_clockevent_init(0, name,
+ 300, iobase, irq, rate);
+ ced->ced.event_handler = clk_event_handle;
+ if (!ced)
+ panic("Unable to initialise clockevent device");
+
+ fh_bc_timer_clockevent_register(ced);
+#ifdef CONFIG_ARM_FULLHAN_CPUIDLE
+ fh_timer_clock_start(&ced->timer);
+ fh_timer_set_periodic(&ced->ced);
+#endif
+}
+
+static void __iomem *sched_io_base;
+static u32 sched_rate;
+
+void __init add_clocksource(struct device_node *source_timer,
+ unsigned int iovbase, unsigned int irqno)
+{
+ void __iomem *iobase = (void __iomem *)iovbase;
+ struct fh_timer_clocksource *cs;
+ u32 rate;
+ const char *name = "timer1";
+
+ if (source_timer != NULL)
+ name = source_timer->name;
+
+
+ timer_get_base_and_rate(source_timer, 1, &iobase, &rate);
+ cs = fh_timer_clocksource_init(300, name, iobase, rate);
+
+ if (!cs)
+ panic("Unable to initialize clocksource device");
+
+ fh_timer_clocksource_start(cs);
+ fh_timer_clocksource_register(cs);
+
+ /*
+ * Fallback to use the clocksource as sched_clock if no separate
+ * timer is found. sched_io_base then points to the current_value
+ * register of the clocksource timer.
+ */
+ sched_io_base = iobase + 0x04;
+
+ sched_rate = rate;
+
+}
+
+static u64 notrace read_sched_clock(void)
+{
+ return ~__raw_readl(sched_io_base);
+}
+
+void __init init_sched_clock(void)
+{
+ sched_clock_register(read_sched_clock, 32, sched_rate);
+}
+
+static int num_called;
+static int __init fh_timer_init(struct device_node *timer)
+{
+ pr_debug("%s-%d\n", __func__, __LINE__);
+ switch (num_called) {
+#if defined(CONFIG_HAVE_ARM_ARCH_TIMER) && defined(CONFIG_SMP)
+ case 0:
+ add_bc_clockevent(timer, 0, 0);
+ /* CREATE BroadCast Timer Only */
+ default:
+ break;
+ }
+#else
+ case 0:
+ pr_debug("%s: found clocksource timer\n", __func__);
+ add_clocksource(timer, 0, 0);
+ init_sched_clock();
+ break;
+ case 1:
+ pr_debug("%s: found clockevent timer\n", __func__);
+ add_clockevent(timer, 0, 0);
+ break;
+ default:
+ break;
+ }
+#endif
+ num_called++;
+ return 0;
+}
+CLOCKSOURCE_OF_DECLARE(fh_timer, "fh,fh-timer", fh_timer_init);
+
+
+void __init fh_timer_init_no_of(unsigned int iovbase,
+ unsigned int irqno)
+{
+ add_clocksource(NULL, iovbase, irqno);
+ init_sched_clock();
+ add_clockevent(NULL, iovbase, irqno);
+}
+
diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm
index 21340e0b..deb7a27a 100644
--- a/drivers/cpuidle/Kconfig.arm
+++ b/drivers/cpuidle/Kconfig.arm
@@ -11,6 +11,12 @@ config ARM_CPUIDLE
initialized by calling the CPU operations init idle hook
provided by architecture code.
+config ARM_FULLHAN_CPUIDLE
+ bool "Fullhan CPU Idle Driver"
+ depends on ARCH_FULLHAN
+ help
+ Select this to enable cpuidle for Fullhan processors
+
config ARM_BIG_LITTLE_CPUIDLE
bool "Support for ARM big.LITTLE processors"
depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 4d2b81f2..ef622402 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -18,7 +18,7 @@ config CRYPTO_DEV_PADLOCK
(so called VIA PadLock ACE, Advanced Cryptography Engine)
that provides instructions for very fast cryptographic
operations with supported algorithms.
-
+
The instructions are used only when the CPU supports them.
Otherwise software encryption is used.
@@ -202,6 +202,10 @@ config CRYPTO_DEV_MARVELL_CESA
This driver is aimed at replacing the mv_cesa driver. This will only
happen once it has received proper testing.
+config FH_CESA_SELF_TEST
+ bool "fh cesa self test"
+ depends on CRYPTO_DEV_FH_CESA
+
config CRYPTO_DEV_NIAGARA2
tristate "Niagara2 Stream Processing Unit driver"
select CRYPTO_DES
@@ -555,4 +559,39 @@ config CRYPTO_DEV_ROCKCHIP
source "drivers/crypto/chelsio/Kconfig"
+choice
+ bool "FH AES driver select"
+ default CRYPTO_DEV_FH_AES
+
+config CRYPTO_DEV_FH_AES
+ tristate "FH AES support(original)"
+# select CRYPTO_BLKCIPHER
+# select CRYPTO_SEQIV
+
+ help
+ To compile this driver as a module, choose M here: the module will
+ be called fh_aes.
+
+config CRYPTO_DEV_FH_AES_TEE
+ tristate "FH AES driver for tee"
+ depends on TEE
+
+ select CRYPTO_BLKCIPHER
+ select CRYPTO_SEQIV
+ help
+ the FH_AES_TEE driver can be chosen when tee is on.
+
+endchoice
+
+config CRYPTO_FH_AES_SUPPORT_DIRECT_MEM
+ bool "direct mem support"
+ depends on CRYPTO_DEV_FH_AES || CRYPTO_DEV_FH_AES_TEE
+ help
+ usr send direct mem to driver.
+
+
+config FH_AES_SELF_TEST
+ bool "fh aes self test"
+ depends on CRYPTO_DEV_FH_AES || CRYPTO_DEV_FH_AES_TEE
+
endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index ad7250fa..420761fc 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -32,3 +32,7 @@ obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/
obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/
obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/
+obj-$(CONFIG_CRYPTO_DEV_FH_AES) += fh_aes.o
+obj-$(CONFIG_CRYPTO_DEV_FH_AES_TEE) += fh_aes_tee.o
+obj-$(CONFIG_FH_AES_SELF_TEST) += fh_aes_test.o
+ccflags-y += -I$(srctree)/drivers/tee/tee_api
diff --git a/drivers/crypto/fh_aes.c b/drivers/crypto/fh_aes.c
new file mode 100644
index 00000000..0d902e2b
--- /dev/null
+++ b/drivers/crypto/fh_aes.c
@@ -0,0 +1,1629 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/irqreturn.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <linux/crc32.h>
+#include <crypto/hash.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <crypto/rng.h>
+#include "fh_aes.h"
+#include <crypto/skcipher.h>
+#include <mach/io.h>
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+
+#define CRYPTO_QUEUE_LEN (1000)
+#define CRYPTION_POS (0)
+#define METHOD_POS (1)
+#define EMODE_POS (4)
+
+#define aes_readl(aes, name) \
+ __raw_readl(&(((struct fh_aes_reg *)aes->regs)->name))
+
+#define aes_writel(aes, name, val) \
+ __raw_writel((val), &(((struct fh_aes_reg *)aes->regs)->name))
+
+#define aes_readw(aes, name) \
+ __raw_readw(&(((struct fh_aes_reg *)aes->regs)->name))
+
+#define aes_writew(aes, name, val) \
+ __raw_writew((val), &(((struct fh_aes_reg *)aes->regs)->name))
+
+#define aes_readb(aes, name) \
+ __raw_readb(&(((struct fh_aes_reg *)aes->regs)->name))
+
+#define aes_writeb(aes, name, val) \
+ __raw_writeb((val), &(((struct fh_aes_reg *)aes->regs)->name))
+
+
+#ifdef CONFIG_FH_EFUSE
+#define FH_AESV2
+#else
+#undef FH_AESV2
+#endif
+
+#define FH_AES_ALLIGN_SIZE 64
+/*
+crypto max malloc the buf size is 4096 for one sg,
+here just cpy all the data to driver pri buf.
+*/
+#define FH_AES_MALLOC_SIZE 2048
+#define FH_AES_CTL_MAX_PROCESS_SIZE (FH_AES_MALLOC_SIZE)
+
+#ifdef FH_AESV2
+#include <linux/fh_efuse.h>
+extern struct wrap_efuse_obj s_efuse_obj;
+#endif
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type that only be used in this file here
+ ***************************************************************************/
+enum {
+ ENCRYPT = 0 << CRYPTION_POS,
+ DECRYPT = 1 << CRYPTION_POS,
+};
+
+enum {
+ ECB_MODE = 0 << EMODE_POS,
+ CBC_MODE = 1 << EMODE_POS,
+ CTR_MODE = 2 << EMODE_POS,
+ CFB_MODE = 4 << EMODE_POS,
+ OFB_MODE = 5 << EMODE_POS,
+};
+
+enum {
+ DES_METHOD = 0 << METHOD_POS,
+ TRIPLE_DES_METHOD = 1 << METHOD_POS,
+ AES_128_METHOD = 4 << METHOD_POS,
+ AES_192_METHOD = 5 << METHOD_POS,
+ AES_256_METHOD = 6 << METHOD_POS,
+};
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+
+static int fh_aes_handle_req(struct fh_aes_dev *dev,
+ struct ablkcipher_request *req);
+/*aes*/
+static int fh_aes_crypt(struct ablkcipher_request *req, unsigned long mode);
+static int fh_aes_ecb_encrypt(struct ablkcipher_request *req);
+static int fh_aes_ecb_decrypt(struct ablkcipher_request *req);
+static int fh_aes_cbc_encrypt(struct ablkcipher_request *req);
+static int fh_aes_cbc_decrypt(struct ablkcipher_request *req);
+static int fh_aes_ctr_encrypt(struct ablkcipher_request *req);
+static int fh_aes_ctr_decrypt(struct ablkcipher_request *req);
+static int fh_aes_ofb_encrypt(struct ablkcipher_request *req);
+static int fh_aes_ofb_decrypt(struct ablkcipher_request *req);
+static int fh_aes_cfb_encrypt(struct ablkcipher_request *req);
+static int fh_aes_cfb_decrypt(struct ablkcipher_request *req);
+
+/*des*/
+static int fh_des_ecb_encrypt(struct ablkcipher_request *req);
+static int fh_des_ecb_decrypt(struct ablkcipher_request *req);
+static int fh_des_cbc_encrypt(struct ablkcipher_request *req);
+static int fh_des_cbc_decrypt(struct ablkcipher_request *req);
+static int fh_des_ofb_encrypt(struct ablkcipher_request *req);
+static int fh_des_ofb_decrypt(struct ablkcipher_request *req);
+static int fh_des_cfb_encrypt(struct ablkcipher_request *req);
+static int fh_des_cfb_decrypt(struct ablkcipher_request *req);
+
+/*tri des*/
+static int fh_des_tri_ecb_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_ecb_decrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cbc_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cbc_decrypt(struct ablkcipher_request *req);
+static int fh_des_tri_ofb_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_ofb_decrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cfb_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cfb_decrypt(struct ablkcipher_request *req);
+static int fh_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key,
+ unsigned int keylen);
+static int fh_aes_cra_init(struct crypto_tfm *tfm);
+static void fh_aes_tx(struct fh_aes_dev *dev);
+static void fh_aes_rx(struct fh_aes_dev *dev);
+static irqreturn_t fh_aes_interrupt(int irq, void *dev_id);
+static void aes_biglittle_swap(u8 *buf);
+static int fh_set_indata(struct fh_aes_dev *dev, struct scatterlist *sg);
+static int fh_set_outdata(struct fh_aes_dev *dev, struct scatterlist *sg);
+static void fh_set_aes_key_reg(struct fh_aes_dev *dev, uint8_t *key,
+ uint8_t *iv, unsigned int keylen);
+static void fh_set_dma_indata(struct fh_aes_dev *dev,
+ struct scatterlist *sg);
+static void fh_set_dma_outdata(struct fh_aes_dev *dev,
+ struct scatterlist *sg);
+static void fh_unset_indata(struct fh_aes_dev *dev);
+static void fh_unset_outdata(struct fh_aes_dev *dev);
+static void fh_aes_complete(struct fh_aes_dev *dev, int err);
+static void fh_aes_crypt_start(struct fh_aes_dev *dev, unsigned long mode);
+static void fh_aes_work_cb(struct work_struct *w);
+static void fh_aes_crypt_with_sg(struct fh_aes_dev *dev,
+unsigned long mode, struct crypto_tfm *tfm);
+#define fh_des_setkey fh_aes_setkey
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+struct fh_aes_dev *pobj_aes_dev = NULL;
+static struct crypto_alg algs[] = {
+ {
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_ecb_encrypt,
+ .decrypt = fh_aes_ecb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_cbc_encrypt,
+ .decrypt = fh_aes_cbc_decrypt,
+ }
+ },
+ {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_ctr_encrypt,
+ .decrypt = fh_aes_ctr_decrypt,
+ }
+ },
+ {
+ .cra_name = "ofb(aes)",
+ .cra_driver_name = "ofb-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_ofb_encrypt,
+ .decrypt = fh_aes_ofb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cfb(aes)",
+ .cra_driver_name = "cfb-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_cfb_encrypt,
+ .decrypt = fh_aes_cfb_decrypt,
+ }
+ },
+ {
+ .cra_name = "ecb(des)",
+ .cra_driver_name = "ecb-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_ecb_encrypt,
+ .decrypt = fh_des_ecb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cbc(des)",
+ .cra_driver_name = "cbc-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_cbc_encrypt,
+ .decrypt = fh_des_cbc_decrypt,
+ }
+ },
+ {
+ .cra_name = "ofb(des)",
+ .cra_driver_name = "ofb-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_ofb_encrypt,
+ .decrypt = fh_des_ofb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cfb(des)",
+ .cra_driver_name = "cfb-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_cfb_encrypt,
+ .decrypt = fh_des_cfb_decrypt,
+ }
+ },
+ {
+ .cra_name = "ecb(des3)",
+ .cra_driver_name = "ecb-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_ecb_encrypt,
+ .decrypt = fh_des_tri_ecb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cbc(des3)",
+ .cra_driver_name = "cbc-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_cbc_encrypt,
+ .decrypt = fh_des_tri_cbc_decrypt,
+ }
+ },
+ {
+ .cra_name = "ofb(des3)",
+ .cra_driver_name = "ofb-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_ofb_encrypt,
+ .decrypt = fh_des_tri_ofb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cfb(des3)",
+ .cra_driver_name = "cfb-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_cfb_encrypt,
+ .decrypt = fh_des_tri_cfb_decrypt,
+ }
+ },
+};
+
+#ifdef CONFIG_FH_AES_SELF_TEST
+extern void fh_aes_self_test_all(void);
+#endif
+
+static unsigned int get_tfm_block_size(struct crypto_tfm *tfm)
+{
+ return tfm->__crt_alg->cra_blocksize;
+}
+/* function body */
+static int fh_aes_handle_req(struct fh_aes_dev *dev,
+ struct ablkcipher_request *req)
+{
+ unsigned long flags;
+ int err;
+ spin_lock_irqsave(&dev->lock, flags);
+ err = ablkcipher_enqueue_request(&dev->queue, req);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ queue_work(dev->workqueue, &dev->work);
+ return err;
+}
+
+static int fh_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
+{
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ struct fh_aes_reqctx *reqctx = ablkcipher_request_ctx(req);
+ struct fh_aes_dev *dev = ctx->dev;
+ AES_DBG("%s\n", __func__);
+ dev->reqctx = reqctx;
+ /*if (!(mode & CFB_MODE)) {*/
+ if ((!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE))
+ && (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE))) {
+ pr_err("request size is not exact amount of AES blocks\n");
+ return -EINVAL;
+ }
+ /*}*/
+ AES_DBG("reqctx->mode value: %x\n", (unsigned int)mode);
+ reqctx->mode = mode;
+ return fh_aes_handle_req(dev, req);
+}
+
+static int fh_aes_ecb_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 method = 0;
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT);
+}
+
+
+static int fh_aes_ecb_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT);
+}
+
+static int fh_aes_cbc_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT);
+}
+
+static int fh_aes_cbc_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT);
+}
+
+static int fh_aes_ctr_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | CTR_MODE | ENCRYPT);
+}
+
+static int fh_aes_ctr_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | CTR_MODE | DECRYPT);
+}
+
+static int fh_aes_ofb_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT);
+}
+
+static int fh_aes_ofb_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT);
+}
+
+static int fh_aes_cfb_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT);
+}
+
+static int fh_aes_cfb_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT);
+}
+static int fh_des_ecb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT);
+}
+
+static int fh_des_ecb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT);
+}
+
+static int fh_des_cbc_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT);
+}
+
+static int fh_des_cbc_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT);
+}
+
+static int fh_des_ofb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT);
+}
+
+static int fh_des_ofb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT);
+}
+
+static int fh_des_cfb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT);
+}
+
+static int fh_des_cfb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT);
+}
+static int fh_des_tri_ecb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_ecb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT);
+}
+
+static int fh_des_tri_cbc_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_cbc_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT);
+}
+
+static int fh_des_tri_ofb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_ofb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT);
+}
+
+static int fh_des_tri_cfb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_cfb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT);
+}
+static int fh_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key,
+ unsigned int keylen)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+ struct fh_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ int i = 0;
+ AES_DBG("%s\n", __func__);
+
+ if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192
+ && keylen != AES_KEYSIZE_256 && keylen != DES_KEY_SIZE
+ && keylen != DES3_EDE_KEY_SIZE)
+ return -EINVAL;
+
+ for (; i < keylen; i++)
+ AES_DBG("%x", key[i]);
+ AES_DBG("\n");
+
+ memcpy(ctx->aes_key, key, keylen);
+ ctx->keylen = keylen;
+ return 0;
+}
+
+static int fh_aes_cra_init(struct crypto_tfm *tfm)
+{
+ struct fh_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ ctx->dev = pobj_aes_dev;
+ tfm->crt_ablkcipher.reqsize = sizeof(struct fh_aes_reqctx);
+ AES_DBG("%s\n", __func__);
+ return 0;
+}
+static void fh_aes_tx(struct fh_aes_dev *dev)
+{
+ /*cpy dri local buf to core sg buf*/
+ unsigned char *dst_xbuf;
+ u32 size = dev->ot_size;
+ u32 cpy_size = 0;
+ u32 i = 0;
+ /* unmap driver buf first.*/
+ fh_unset_outdata(dev);
+ dst_xbuf = &dev->ctl_dst_xbuf[0];
+ do {
+ /*get the sg list offset left
+ and the xfer size lower one.*/
+ cpy_size = min_t(u32,
+ sg_dma_len(dev->sg_dst) - dev->dst_sg_offset, size);
+ sg_pcopy_from_buffer(dev->sg_dst, 1,
+ &dst_xbuf[i], cpy_size, dev->dst_sg_offset);
+ i += cpy_size;
+ dev->dst_sg_offset += cpy_size;
+ size -= cpy_size;
+ if (dev->dst_sg_offset == sg_dma_len(dev->sg_dst)) {
+ /*if sg offset get to the end of sg list.
+ then find the next..*/
+ dev->dst_sg_offset = 0;
+ dev->sg_dst = sg_next(dev->sg_dst);
+ }
+ } while (size);
+
+}
+
+static void fh_aes_rx(struct fh_aes_dev *dev)
+{
+ fh_unset_indata(dev);
+}
+
+
+static irqreturn_t fh_aes_interrupt(int irq, void *dev_id)
+{
+
+ u32 isr_status;
+ /*unsigned long flags;*/
+ struct platform_device *pdev = (struct platform_device *) dev_id;
+ struct fh_aes_dev *dev = platform_get_drvdata(pdev);
+ /*u32 isr = dev->en_isr;*/
+ AES_DBG("%s\n", __func__);
+ /*spin_lock_irqsave(&dev->lock, flags);*/
+ aes_writel(dev, dma_control, 0);
+ isr_status = aes_readl(dev, intr_src);
+ aes_writel(dev, intr_clear_status, 0x07);
+ aes_writel(dev, intr_enable, 0);
+ if (isr_status & 0x02)
+ pr_err("dma rev hreap error...\n");
+ if (isr_status & 0x04)
+ pr_err("dma stop src ..\n");
+ if (isr_status & 0x01) {
+ AES_DBG("dma done..\n");
+ complete(&(dev->done));
+ }
+ /*spin_unlock_irqrestore(&dev->lock, flags);*/
+ return IRQ_HANDLED;
+}
+
+static void aes_biglittle_swap(u8 *buf)
+{
+ u8 tmp, tmp1;
+ tmp = buf[0];
+ tmp1 = buf[1];
+ buf[0] = buf[3];
+ buf[1] = buf[2];
+ buf[2] = tmp1;
+ buf[3] = tmp;
+}
+
+static int fh_set_indata(struct fh_aes_dev *dev, struct scatterlist *sg)
+{
+ /*cpy usr buf data to dri local buf*/
+ unsigned char *src_xbuf;
+ int err;
+ u32 cpy_size = 0;
+ u32 i = 0;
+ u32 size = dev->ot_size;
+ src_xbuf = &dev->ctl_src_xbuf[0];
+
+ do {
+ /*get the sg list offset left and the xfer size lower one.*/
+ cpy_size = min_t(u32,
+ sg_dma_len(dev->sg_src) - dev->src_sg_offset, size);
+ sg_pcopy_to_buffer(dev->sg_src, 1,
+ &src_xbuf[i], cpy_size, dev->src_sg_offset);
+ i += cpy_size;
+ dev->src_sg_offset += cpy_size;
+ size -= cpy_size;
+ if (dev->src_sg_offset == sg_dma_len(dev->sg_src)) {
+ /*if sg offset get to the end of sg list.
+ then find the next..*/
+ dev->src_sg_offset = 0;
+ dev->sg_src = sg_next(dev->sg_src);
+ }
+ } while (size);
+ /* cpy core date to driver buf, map the driver sg*/
+ sg_init_one(&dev->src_sg_array[0], &src_xbuf[0], dev->ot_size);
+ err = dma_map_sg(dev->dev, &dev->src_sg_array[0], 1, DMA_TO_DEVICE);
+ if (!err)
+ BUG();
+ return err;
+}
+
+static int fh_set_outdata(struct fh_aes_dev *dev, struct scatterlist *sg)
+{
+ int err;
+ /*out data to driver buf, then cpy to core buf*/
+ sg_init_one(&dev->dst_sg_array[0],
+ &dev->ctl_dst_xbuf[0], dev->ot_size);
+ err = dma_map_sg(dev->dev, &dev->dst_sg_array[0], 1, DMA_FROM_DEVICE);
+ if (!err)
+ BUG();
+ return err;
+}
+
+/*if use (encrypt & secure boot & use efuse 0~15 entry). return err*/
+int fh_aes_secure_check(struct fh_aes_dev *dev)
+{
+ if (dev->control_reg & DECRYPT) {
+ return 0;
+ }
+ return fh_efuse_secure_check(&s_efuse_obj,
+ s_efuse_obj.trans_key_start_no,
+ s_efuse_obj.trans_key_size, dev->p_usr_def);
+}
+
+static void fh_set_aes_key_reg(struct fh_aes_dev *dev, uint8_t *key,
+ uint8_t *iv, unsigned int keylen)
+{
+
+ int i;
+ u32 method;
+ u32 temp_key_buf[32];
+ u32 temp_iv_buf[32];
+ u32 *p_dst = NULL;
+ u32 key_size = 0;
+
+ if (dev->iv_flag == true) {
+ /*set iv*/
+ /*if aes mode ....set 128 bit iv, des set 64bit iv..*/
+ AES_DBG("set iv reg\n");
+ if ((dev->control_reg & AES_128_METHOD)
+ || ((dev->control_reg & AES_192_METHOD))
+ || (dev->control_reg & AES_256_METHOD)) {
+ AES_DBG("aes iv mode...\n");
+
+ memcpy((u8 *)&temp_iv_buf[0], iv, 16);
+ p_dst = &temp_iv_buf[0];
+ for (i = 0; i < 16 / sizeof(u32); i++)
+ aes_biglittle_swap((u8 *)(p_dst + i));
+ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->initial_vector0,
+ temp_iv_buf, 16);
+ } else {
+ AES_DBG("des iv mode...\n");
+
+ memcpy((u8 *)&temp_iv_buf[0], iv, 8);
+ p_dst = &temp_iv_buf[0];
+ for (i = 0; i < 8 / sizeof(u32); i++)
+ aes_biglittle_swap((u8 *)(p_dst + i));
+
+ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->initial_vector0,
+ temp_iv_buf, 8);
+
+ }
+ }
+ /*set key...*/
+ method = dev->control_reg & 0x0e;
+ AES_DBG("set key reg\n");
+
+ switch (method) {
+ case AES_128_METHOD:
+ AES_DBG("set key aes 128 mode..\n");
+ key_size = 16;
+
+ break;
+ case AES_192_METHOD:
+ AES_DBG("set key aes 192 mode..\n");
+ key_size = 24;
+ break;
+
+ case AES_256_METHOD:
+ AES_DBG("set key aes 256 mode..\n");
+ key_size = 32;
+ break;
+
+ case DES_METHOD:
+ AES_DBG("set key des normal mode..\n");
+ key_size = 8;
+ break;
+
+ case TRIPLE_DES_METHOD:
+ AES_DBG("set key des triple mode..\n");
+ key_size = 24;
+ break;
+
+ default:
+ AES_DBG("error method!!\n");
+ break;
+ }
+#ifdef FH_AESV2
+ if (dev->p_usr_def->mode & CRYPTO_EX_MEM_SET_KEY) {
+ s_efuse_obj.trans_key_start_no = 0;
+ s_efuse_obj.trans_key_size = key_size / 4;
+ if (fh_aes_secure_check(dev)) {
+ pr_err("secure check failed..\n");
+ return;
+ }
+ efuse_trans_key(&s_efuse_obj,
+ s_efuse_obj.trans_key_start_no,
+ s_efuse_obj.trans_key_size, dev->p_usr_def);
+ } else {
+ s_efuse_obj.old_usr_def.mode &= ~CRYPTO_EX_MEM_SET_KEY;
+ s_efuse_obj.old_usr_def.mode |= CRYPTO_CPU_SET_KEY;
+ memcpy((u8 *)&temp_key_buf[0], key, key_size);
+ p_dst = &temp_key_buf[0];
+ for (i = 0; i < key_size / sizeof(u32); i++)
+ aes_biglittle_swap((u8 *)(p_dst + i));
+ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->security_key0,
+ (u8 *)&temp_key_buf[0],
+ key_size);
+ }
+
+#else
+ memcpy((u8 *)&temp_key_buf[0], key, key_size);
+ p_dst = &temp_key_buf[0];
+ for (i = 0; i < key_size / sizeof(u32); i++)
+ aes_biglittle_swap((u8 *)(p_dst + i));
+
+ memcpy((u8 *)&((struct fh_aes_reg *) dev->regs)->security_key0,
+ (u8 *)&temp_key_buf[0],
+ key_size);
+#endif
+}
+
+static void fh_set_dma_indata(struct fh_aes_dev *dev,
+ struct scatterlist *sg)
+{
+ aes_writel(dev, dma_src_add, sg_dma_address(sg));
+ AES_DBG("%s :dma trans size is :%x,add is:%x\n",
+ __func__, sg_dma_len(sg), sg_dma_address(sg));
+ aes_writel(dev, dma_trans_size, sg_dma_len(sg));
+}
+
+static void fh_set_dma_outdata(struct fh_aes_dev *dev,
+ struct scatterlist *sg)
+{
+ aes_writel(dev, dma_dst_add, sg_dma_address(sg));
+}
+static void fh_unset_indata(struct fh_aes_dev *dev)
+{
+ dma_unmap_sg(dev->dev, &dev->src_sg_array[0], 1, DMA_TO_DEVICE);
+}
+
+static void fh_unset_outdata(struct fh_aes_dev *dev)
+{
+ dma_unmap_sg(dev->dev, &dev->dst_sg_array[0], 1, DMA_FROM_DEVICE);
+}
+static void fh_aes_complete(struct fh_aes_dev *dev, int err)
+{
+ if (dev->req->base.complete)
+ dev->req->base.complete(&dev->req->base, err);
+}
+
+
+static void fh_aes_crypt_start(struct fh_aes_dev *dev,
+unsigned long mode)
+{
+ struct crypto_tfm *tfm;
+ struct crypto_ablkcipher *p_tfm;
+ struct ablkcipher_request *req;
+
+ req = dev->req;
+ p_tfm = crypto_ablkcipher_reqtfm(dev->req);
+ tfm = crypto_ablkcipher_tfm(p_tfm);
+ fh_aes_crypt_with_sg(dev, mode, tfm);
+
+ return;
+
+}
+
+static u32 fh_aes_update_request_data_size(u32 max_xfer_size,
+u32 *total_size, u32 *first)
+{
+ u32 step_size = 0;
+
+ step_size = min_t(u32, *total_size, max_xfer_size);
+ if (*first == 0)
+ *first = 1;
+
+ *total_size -= step_size;
+ return step_size;
+}
+
+static void fh_aes_crypt_with_sg(struct fh_aes_dev *dev,
+unsigned long mode, struct crypto_tfm *tfm)
+{
+ struct ablkcipher_request *req = dev->req;
+ u32 total_size;
+ u32 block_size_limit;
+ u32 ot_len;
+ u32 isr;
+ u32 outfifo_thold = 0;
+ u32 infifo_thold = 0;
+ u32 first_in = 0;
+ u32 control_reg = 0;
+
+ total_size = req->nbytes;
+ block_size_limit = get_tfm_block_size(tfm);
+ dev->sg_src = req->src;
+ dev->sg_dst = req->dst;
+ dev->src_sg_offset = 0;
+ dev->dst_sg_offset = 0;
+
+ while (total_size) {
+ init_completion(&dev->done);
+ if (((mode & CBC_MODE) || (mode & CTR_MODE) || (mode & CFB_MODE)
+ || (mode & OFB_MODE)) && (first_in == 0)) {
+ control_reg |= 1 << 7;
+ dev->iv_flag = true;
+ } else {
+ control_reg &= ~(1 << 7);
+ dev->iv_flag = false;
+ }
+
+ /*emode & method*/
+ control_reg |= (unsigned int) mode;
+ dev->control_reg = control_reg;
+ outfifo_thold = 0;
+ infifo_thold = 8;
+ isr = dev->en_isr;
+ aes_writel(dev, encrypt_control, control_reg);
+ /*set key...*/
+ if (first_in == 0)
+ fh_set_aes_key_reg(dev, dev->ctx->aes_key,
+ req->info, dev->ctx->keylen);
+
+ ot_len = fh_aes_update_request_data_size(
+ FH_AES_CTL_MAX_PROCESS_SIZE,
+ &total_size, &first_in);
+ if (ot_len % block_size_limit)
+ BUG();
+ dev->ot_size = ot_len;
+ fh_set_indata(dev, &dev->src_sg_array[0]);
+ fh_set_outdata(dev, &dev->dst_sg_array[0]);
+ fh_set_dma_indata(dev, &dev->src_sg_array[0]);
+ fh_set_dma_outdata(dev, &dev->dst_sg_array[0]);
+ aes_writel(dev, fifo_threshold,
+ outfifo_thold << 8 | infifo_thold);
+ /*set isr..*/
+ aes_writel(dev, intr_enable, isr);
+ /*enable dma go..*/
+ aes_writel(dev, dma_control, 1);
+ wait_for_completion(&dev->done);
+ /*update dst sg...*/
+ fh_aes_rx(dev);
+ fh_aes_tx(dev);
+ }
+
+}
+#ifdef CONFIG_CRYPTODEV
+void cryptodev_fix_key_mode(struct fh_aes_ctx *p_ctx,
+struct af_alg_usr_def *p_usr_def)
+{
+ uint8_t *pkey;
+
+ pkey = p_ctx->aes_key;
+ if (pkey[0] == 'f' && pkey[1] == 'u' && pkey[2] == 'l'
+ && pkey[3] == 'l' && pkey[4] == 'h'
+ && pkey[5] == 'a' && pkey[6] == 'n') {
+ p_usr_def->mode &=
+ ~(CRYPTO_CPU_SET_KEY | CRYPTO_EX_MEM_SET_KEY);
+ p_usr_def->mode |=
+ CRYPTO_EX_MEM_SET_KEY;
+ }
+}
+#endif
+
+static void fh_aes_work_cb(struct work_struct *w)
+{
+ struct fh_aes_dev *dev = container_of(w, struct fh_aes_dev, work);
+ struct crypto_async_request *async_req, *backlog;
+ struct fh_aes_reqctx *reqctx;
+ struct crypto_ablkcipher *p_tfm;
+ struct af_alg_usr_def *p_usr_def;
+ unsigned long flags;
+ struct ablkcipher_request *p_ablk_req;
+
+ AES_DBG("%s\n", __func__);
+ /*get the req need to handle*/
+ spin_lock_irqsave(&dev->lock, flags);
+ async_req = crypto_dequeue_request(&dev->queue);
+ backlog = crypto_get_backlog(&dev->queue);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ if (!async_req)
+ return;
+
+ dev->req = ablkcipher_request_cast(async_req);
+ p_tfm = crypto_ablkcipher_reqtfm(dev->req);
+ p_ablk_req = dev->req;
+ p_usr_def = p_ablk_req->usr_def;
+ /*p_usr_def = crypto_ablkcipher_usr_def(p_tfm);*/
+ dev->p_usr_def = p_usr_def;
+ dev->ctx = crypto_tfm_ctx(dev->req->base.tfm);
+ reqctx = ablkcipher_request_ctx(dev->req);
+#ifdef CONFIG_CRYPTODEV
+ cryptodev_fix_key_mode(dev->ctx, p_usr_def);
+#endif
+
+ fh_aes_crypt_start(dev, reqctx->mode);
+ fh_aes_complete(dev, 0);
+ if (backlog) {
+ if (backlog->complete)
+ backlog->complete(backlog, -EINPROGRESS);
+ }
+ /*call the queue work until empty.*/
+ if (dev->queue.qlen != 0)
+ queue_work(dev->workqueue, &dev->work);
+}
+
+
+int fh_aes_ctl_mem_init(struct fh_aes_dev *pdata)
+{
+ unsigned int t1;
+ unsigned int t2;
+ unsigned int t3;
+ unsigned int t4;
+
+ t1 = (unsigned int)kmalloc(FH_AES_MALLOC_SIZE
+ + FH_AES_ALLIGN_SIZE, GFP_KERNEL);
+ if (!t1)
+ goto err1;
+
+ t2 = (unsigned int)kmalloc(FH_AES_MALLOC_SIZE
+ + FH_AES_ALLIGN_SIZE, GFP_KERNEL);
+ if (!t2)
+ goto err2;
+
+
+ t3 = ((t1 + FH_AES_ALLIGN_SIZE - 1) & (~(FH_AES_ALLIGN_SIZE - 1)));
+ t4 = ((t2 + FH_AES_ALLIGN_SIZE - 1) & (~(FH_AES_ALLIGN_SIZE - 1)));
+
+ pdata->ctl_raw_src_xbuf = (unsigned char *)t1;
+ pdata->ctl_raw_dst_xbuf = (unsigned char *)t2;
+ pdata->ctl_src_xbuf = (unsigned char *)t3;
+ pdata->ctl_dst_xbuf = (unsigned char *)t4;
+ return 0;
+err2:
+ kfree((void *)t1);
+err1:
+ return -1;
+
+}
+
+static int fh_aes_probe(struct platform_device *pdev)
+{
+
+ int i, j, err = -ENODEV;
+ struct fh_aes_dev *pdata;
+ struct resource *res;
+ struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
+
+ pdata = kzalloc(sizeof(struct fh_aes_dev), GFP_KERNEL);
+ if (!pdata) {
+ err = -ENOMEM;
+ goto err_malloc;
+ }
+ spin_lock_init(&pdata->lock);
+
+ if (np && !IS_ERR(np)) {
+ pdata->regs = of_iomap(np, 0);
+ if (!pdata->regs) {
+ err = -EINVAL;
+ goto err_iomap;
+ }
+ pdata->irq_no = irq_of_parse_and_map(np, 0);
+ if (!pdata->irq_no) {
+ err = pdata->irq_no;
+ goto err_irq;
+ }
+ } else {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ goto err_iomap;
+ }
+
+ pdata->regs = ioremap(res->start, resource_size(res));
+ if (pdata->regs == NULL) {
+ dev_err(&pdev->dev, "ioremap resource error\n");
+ goto err_iomap;
+ }
+
+ pdata->irq_no = irq_create_mapping(NULL, platform_get_irq(pdev, 0));
+ if (pdata->irq_no < 0) {
+ dev_err(&pdev->dev, "aes interrupt is not available.\n");
+ goto err_irq;
+ }
+ }
+
+ pdata->en_isr = 1 << 0;
+ err = request_irq(pdata->irq_no, fh_aes_interrupt, 0,
+ "fh-aes", pdev);
+ if (err) {
+ dev_dbg(&pdev->dev, "request_irq failed, %d\n", err);
+ goto err_irq;
+ }
+ /*bind to plat dev..*/
+ pdata->dev = dev;
+ /*bing to static para..only one aes controller in fh..*/
+ pobj_aes_dev = pdata;
+ platform_set_drvdata(pdev, pdata);
+
+ pdata->workqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
+ if (!pdata->workqueue) {
+ dev_err(&pdev->dev, "aes workqueue init error.\n");
+ goto err_irq;
+ }
+ INIT_WORK(&pdata->work, fh_aes_work_cb);
+ crypto_init_queue(&pdata->queue, CRYPTO_QUEUE_LEN);
+ for (i = 0; i < ARRAY_SIZE(algs); i++) {
+ INIT_LIST_HEAD(&algs[i].cra_list);
+ err = crypto_register_alg(&algs[i]);
+
+ if (err) {
+ dev_warn(dev, "register alg error...\n");
+ goto err_algs;
+ }
+ }
+
+ err = fh_aes_ctl_mem_init(pdata);
+ if (err) {
+ dev_err(&pdev->dev, "aes malloc mem error..\n");
+ goto err_algs;
+ }
+ pr_info("aes driver registered\n");
+
+
+#ifdef CONFIG_FH_AES_SELF_TEST
+
+ fh_aes_self_test_all();
+#endif
+
+ return 0;
+err_algs:
+ for (j = 0; j < i; j++)
+ crypto_unregister_alg(&algs[j]);
+ destroy_workqueue(pdata->workqueue);
+ platform_set_drvdata(pdev, NULL);
+ pobj_aes_dev = NULL;
+ free_irq(pdata->irq_no, pdata);
+
+err_irq:
+err_iomap:
+ kfree(pdata);
+err_malloc:
+
+ return err;
+
+}
+
+
+static int fh_aes_remove(struct platform_device *pdev)
+{
+
+ int i;
+ struct fh_aes_dev *pdata = platform_get_drvdata(pdev);
+
+ for (i = 0; i < ARRAY_SIZE(algs); i++)
+ crypto_unregister_alg(&algs[i]);
+
+ destroy_workqueue(pdata->workqueue);
+ platform_set_drvdata(pdev, NULL);
+ pobj_aes_dev = NULL;
+ free_irq(pdata->irq_no, pdata);
+ iounmap(pdata->regs);
+ kfree(pdata->ctl_raw_src_xbuf);
+ kfree(pdata->ctl_raw_dst_xbuf);
+ pdata->ctl_raw_src_xbuf = NULL;
+ pdata->ctl_raw_dst_xbuf = NULL;
+ pdata->ctl_src_xbuf = NULL;
+ pdata->ctl_dst_xbuf = NULL;
+ kfree(pdata);
+
+ return 0;
+}
+
+
+
+/*add chenjn dsp use...*/
+typedef struct {
+ unsigned int base;
+ void *vbase;
+ unsigned int size;
+} MEM_INFO;
+
+typedef struct {
+ MEM_INFO mem;
+ unsigned char *remap_base;
+} RW_MEM_INFO;
+
+struct tcrypt_result {
+ struct completion completion;
+ int err;
+};
+
+static void tcrypt_complete(struct crypto_async_request *req, int err)
+{
+ struct tcrypt_result *res = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+ complete(&res->completion);
+}
+
+int aes_128_ecb_encrypt(char *key_128, RW_MEM_INFO in,
+RW_MEM_INFO out, unsigned int data_len_align16)
+{
+ static char *xbuf;
+ static char *dst_xbuf;
+ static struct crypto_ablkcipher *tfm;
+ static struct ablkcipher_request *req;
+ static struct af_alg_usr_def usr_def = {0};
+ static int malloc_flag;
+ /*const char *algo = NULL;*/
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ void *data;
+ void *dst_data;
+ struct tcrypt_result wait_result;
+
+ /*malloc buf...*/
+ if (malloc_flag != 0)
+ goto work_go;
+ malloc_flag = 1;
+
+ usr_def.mode = CRYPTO_CPU_SET_KEY;
+
+ xbuf = (void *)__get_free_page(GFP_KERNEL);
+ if (!xbuf) {
+ pr_err("no pages.\n");
+ return -1;
+ }
+ dst_xbuf = (void *)__get_free_page(GFP_KERNEL);
+ if (!dst_xbuf) {
+ free_page((unsigned long)xbuf);
+ pr_err("no pages.\n");
+ return -1;
+ }
+ tfm = crypto_alloc_ablkcipher("ecb-aes-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(tfm)) {
+ pr_err("aes_test: failed to alloc cipher!\n");
+ free_page((unsigned long)xbuf);
+ free_page((unsigned long)dst_xbuf);
+ return -1;
+ }
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ pr_err("alg: skcipher: Failed to allocate\n");
+ return -1;
+ }
+
+work_go:
+ ablkcipher_request_set_usrdef(req, &usr_def);
+ init_completion(&wait_result.completion);
+ crypto_ablkcipher_setkey(tfm, (u8 *)key_128, 16);
+
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &wait_result);
+
+ data = xbuf;
+ dst_data = dst_xbuf;
+ /*encrypt*/
+ memcpy(data, in.remap_base, data_len_align16);
+ sg_init_one(&sg[0], data, data_len_align16);
+ sg_init_one(&dst_sg[0], dst_data, data_len_align16);
+ ablkcipher_request_set_crypt(req, sg, dst_sg, data_len_align16, NULL);
+ crypto_ablkcipher_encrypt(req);
+ wait_for_completion(&wait_result.completion);
+ memcpy(out.remap_base, dst_data, data_len_align16);
+
+ return 0;
+
+}
+EXPORT_SYMBOL(aes_128_ecb_encrypt);
+
+static const struct of_device_id fh_aes_of_match[] = {
+ {.compatible = "fh,fh-aes",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_aes_of_match);
+
+static struct platform_driver fh_aes_driver = {
+ .driver = {
+ .name = "fh_aes",
+ .of_match_table = fh_aes_of_match,
+ },
+ .probe = fh_aes_probe,
+ .remove = fh_aes_remove,
+};
+
+module_platform_driver(fh_aes_driver);
+MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>");
+MODULE_DESCRIPTION("fullhan AES device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/fh_aes.h b/drivers/crypto/fh_aes.h
new file mode 100644
index 00000000..369a6761
--- /dev/null
+++ b/drivers/crypto/fh_aes.h
@@ -0,0 +1,118 @@
+#ifndef FH_AES_H_
+#define FH_AES_H_
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/crypto.h>
+#include <linux/interrupt.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <crypto/des.h>
+#include <crypto/ctr.h>
+
+struct fh_aes_reg {
+ u32 encrypt_control; /*0*/
+ u32 reserved_4_8; /*4*/
+ u32 fifo_status; /*8*/
+ u32 parity_error; /*c*/
+ u32 security_key0; /*10*/
+ u32 security_key1; /*14*/
+ u32 security_key2; /*18*/
+ u32 security_key3; /*1c*/
+ u32 security_key4; /*20*/
+ u32 security_key5; /*24*/
+ u32 security_key6; /*28*/
+ u32 security_key7; /*2c*/
+ u32 initial_vector0; /*30*/
+ u32 initial_vector1; /*34*/
+ u32 initial_vector2; /*38*/
+ u32 initial_vector3; /*3c*/
+ u32 reserved_40_44; /*40*/
+ u32 reserved_44_48; /*44*/
+ u32 dma_src_add; /*48*/
+ u32 dma_dst_add; /*4c*/
+ u32 dma_trans_size; /*50*/
+ u32 dma_control; /*54*/
+ u32 fifo_threshold; /*58*/
+ u32 intr_enable; /*5c*/
+ u32 intr_src; /*60*/
+ u32 mask_intr_status; /*64*/
+ u32 intr_clear_status; /*68*/
+ u32 reserved_6c_70; /*6c*/
+ u32 revision; /*70*/
+ u32 feature; /*74*/
+ u32 reserved_78_7c; /*78*/
+ u32 reserved_7c_80; /*7c*/
+ u32 last_initial_vector0; /*80*/
+ u32 last_initial_vector1; /*84*/
+ u32 last_initial_vector2; /*88*/
+ u32 last_initial_vector3; /*8c*/
+};
+
+/*requst ctx.....*/
+struct fh_aes_reqctx {
+ unsigned long mode;
+};
+/*aes ctx....*/
+struct fh_aes_ctx {
+ struct fh_aes_dev *dev; /*bind to aes dev..*/
+ uint8_t aes_key[AES_MAX_KEY_SIZE]; /*rec key value..*/
+ int keylen; /*rec key len.*/
+};
+
+struct fh_aes_dev {
+ /*common driver paras..*/
+ void *regs;
+ struct device *dev; /*bind to the platform dev...*/
+ struct clk *clk;
+ spinlock_t lock; /*just lock...*/
+ u32 irq_no; /*board info...*/
+ u32 en_isr; /*software rec the isr src*/
+ bool iv_flag;
+ u32 control_reg;
+ /*crypto need below...*/
+ struct fh_aes_ctx *ctx; /*bind to the aes ctx...*/
+ struct fh_aes_reqctx *reqctx; /*bind to the req ctx..*/
+ struct scatterlist *sg_src; /*rec the src data need to be handled*/
+ struct scatterlist *sg_dst; /*rec the dst data need to be handled*/
+ struct tasklet_struct tasklet; /*async process the crypto*/
+ struct ablkcipher_request *req; /*active req...*/
+ struct crypto_queue queue;
+ unsigned char *ctl_src_xbuf;
+ unsigned char *ctl_dst_xbuf;
+ unsigned char *ctl_raw_src_xbuf;
+ unsigned char *ctl_raw_dst_xbuf;
+ u32 src_sg_offset;
+ u32 dst_sg_offset;
+ struct scatterlist src_sg_array[1];
+ struct scatterlist dst_sg_array[1];
+ u32 ot_size;
+ struct completion done;
+ struct workqueue_struct *workqueue;
+ struct work_struct work;
+ struct af_alg_usr_def *p_usr_def;
+};
+
+
+/*#define FH_AES_SELF_TEST*/
+/*#define FH_AES_DEBUG*/
+#ifdef FH_AES_DEBUG
+#define AES_DBG(fmt, args...) printk(fmt, ## args)
+#else
+#define AES_DBG(fmt, args...) do { } while (0)
+#endif
+
+#define AES_PRINT_RESULT(fmt, args...) printk(fmt, ## args)
+
+#endif /* fh_AES_H_ */
+
+
diff --git a/drivers/crypto/fh_aes_tee.c b/drivers/crypto/fh_aes_tee.c
new file mode 100644
index 00000000..2670a42e
--- /dev/null
+++ b/drivers/crypto/fh_aes_tee.c
@@ -0,0 +1,1503 @@
+#define pr_fmt(fmt) "%s %d: " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/irqreturn.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <linux/crc32.h>
+#include <crypto/hash.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <crypto/rng.h>
+#include "fh_aes.h"
+#include <crypto/skcipher.h>
+#include <mach/io.h>
+#include <tee_client_api.h>
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+
+#define CRYPTO_QUEUE_LEN (1000)
+#define CRYPTION_POS (0)
+#define METHOD_POS (1)
+#define EMODE_POS (4)
+
+
+#define FH_AES_ALLIGN_SIZE 64
+#define FH_AES_MALLOC_SIZE 2048
+#define FH_AES_CTL_MAX_PROCESS_SIZE (FH_AES_MALLOC_SIZE)
+
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type that only be used in this file here
+ ***************************************************************************/
+enum {
+ ENCRYPT = 0 << CRYPTION_POS,
+ DECRYPT = 1 << CRYPTION_POS,
+};
+
+enum {
+ ECB_MODE = 0 << EMODE_POS,
+ CBC_MODE = 1 << EMODE_POS,
+ CTR_MODE = 2 << EMODE_POS,
+ CFB_MODE = 4 << EMODE_POS,
+ OFB_MODE = 5 << EMODE_POS,
+};
+
+enum {
+ DES_METHOD = 0 << METHOD_POS,
+ TRIPLE_DES_METHOD = 1 << METHOD_POS,
+ AES_128_METHOD = 4 << METHOD_POS,
+ AES_192_METHOD = 5 << METHOD_POS,
+ AES_256_METHOD = 6 << METHOD_POS,
+};
+
+/* optee TA UUID and cmds defines */
+static TEEC_UUID TA_FH_AES_UUID = \
+ { 0xdd00d7bd, 0xe9e3, 0x4dcb,\
+ { 0xad, 0xbc, 0xda, 0x54, 0xa7, 0x1b, 0x9b, 0x65} };
+
+#define TA_INVOKE_AES_PREPARE 1
+#define TA_INVOKE_AES_SET_KEY 2
+#define TA_INVOKE_AES_SET_IV 3
+#define TA_INVOKE_AES_ENCRYPT 4
+#define TA_INVOKE_AES_DECRYPT 5
+#define TA_INVOKE_AES_START_TRANSFER 6
+
+static TEEC_Context ctx;
+static TEEC_Session sess;
+
+static int tee_fh_aes_set_key(void *key, struct ex_key_map_para *key_map, size_t size)
+{
+ uint32_t paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+
+ memset(params, 0, sizeof(params));
+ params[0].tmpref.buffer = key;
+ params[0].tmpref.size = size;
+
+ if (key_map) {
+ paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT,
+ TEEC_NONE, TEEC_NONE);
+ params[1].tmpref.buffer = key_map;
+ params[1].tmpref.size = sizeof(*key_map);
+ }
+
+ return tee_invoke_cmd(&sess, TA_INVOKE_AES_SET_KEY, paramTypes, params);
+}
+
+static int tee_fh_aes_set_iv(void *iv, size_t size)
+{
+ uint32_t paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+
+ memset(params, 0, sizeof(params));
+
+ params[0].tmpref.buffer = iv;
+ params[0].tmpref.size = size;
+
+ return tee_invoke_cmd(&sess, TA_INVOKE_AES_SET_IV, paramTypes, params);
+}
+
+static int tee_fh_aes_prepare(int type, int mode, int flag)
+{
+ uint32_t paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT,
+ TEEC_VALUE_INPUT, TEEC_NONE);
+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+
+ memset(params, 0, sizeof(params));
+
+ params[0].value.a = type;
+ params[1].value.a = mode;
+ params[2].value.a = flag;
+
+ pr_debug("%x %x %x\n", type, mode, flag);
+
+ return tee_invoke_cmd(&sess, TA_INVOKE_AES_PREPARE, paramTypes, params);
+}
+
+static int tee_fh_aes_start_transfer(void)
+{
+ uint32_t paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+
+ memset(params, 0, sizeof(params));
+
+
+ pr_debug("aes start transfer\n");
+
+ return tee_invoke_cmd(&sess, TA_INVOKE_AES_START_TRANSFER, paramTypes, params);
+}
+
+static int tee_fh_aes_crypto_action(void *src, void *dst, size_t size, int action)
+{
+ uint32_t paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_OUTPUT,
+ TEEC_NONE, TEEC_NONE);
+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+
+ memset(params, 0, sizeof(params));
+ params[0].tmpref.buffer = src;
+ params[0].tmpref.size = size;
+ params[1].tmpref.buffer = dst;
+ params[1].tmpref.size = size;
+
+ return tee_invoke_cmd(&sess, action, paramTypes, params);
+}
+
+static int tee_fh_aes_encrypt(void *src, void *dst, size_t size)
+{
+ return tee_fh_aes_crypto_action(src, dst, size, TA_INVOKE_AES_ENCRYPT);
+}
+
+static int tee_fh_aes_decrypt(void *src, void *dst, size_t size)
+{
+ return tee_fh_aes_crypto_action(src, dst, size, TA_INVOKE_AES_DECRYPT);
+}
+
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+
+static int fh_aes_handle_req(struct fh_aes_dev *dev,
+ struct ablkcipher_request *req);
+/*aes*/
+static int fh_aes_crypt(struct ablkcipher_request *req, unsigned long mode);
+static int fh_aes_ecb_encrypt(struct ablkcipher_request *req);
+static int fh_aes_ecb_decrypt(struct ablkcipher_request *req);
+static int fh_aes_cbc_encrypt(struct ablkcipher_request *req);
+static int fh_aes_cbc_decrypt(struct ablkcipher_request *req);
+static int fh_aes_ctr_encrypt(struct ablkcipher_request *req);
+static int fh_aes_ctr_decrypt(struct ablkcipher_request *req);
+static int fh_aes_ofb_encrypt(struct ablkcipher_request *req);
+static int fh_aes_ofb_decrypt(struct ablkcipher_request *req);
+static int fh_aes_cfb_encrypt(struct ablkcipher_request *req);
+static int fh_aes_cfb_decrypt(struct ablkcipher_request *req);
+
+/*des*/
+static int fh_des_ecb_encrypt(struct ablkcipher_request *req);
+static int fh_des_ecb_decrypt(struct ablkcipher_request *req);
+static int fh_des_cbc_encrypt(struct ablkcipher_request *req);
+static int fh_des_cbc_decrypt(struct ablkcipher_request *req);
+static int fh_des_ofb_encrypt(struct ablkcipher_request *req);
+static int fh_des_ofb_decrypt(struct ablkcipher_request *req);
+static int fh_des_cfb_encrypt(struct ablkcipher_request *req);
+static int fh_des_cfb_decrypt(struct ablkcipher_request *req);
+
+/*tri des*/
+static int fh_des_tri_ecb_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_ecb_decrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cbc_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cbc_decrypt(struct ablkcipher_request *req);
+static int fh_des_tri_ofb_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_ofb_decrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cfb_encrypt(struct ablkcipher_request *req);
+static int fh_des_tri_cfb_decrypt(struct ablkcipher_request *req);
+static int fh_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key,
+ unsigned int keylen);
+static int fh_aes_cra_init(struct crypto_tfm *tfm);
+static void fh_aes_tx(struct fh_aes_dev *dev);
+static void fh_aes_rx(struct fh_aes_dev *dev);
+static int fh_set_indata(struct fh_aes_dev *dev, struct scatterlist *sg);
+static int fh_set_outdata(struct fh_aes_dev *dev, struct scatterlist *sg);
+static void fh_set_aes_key_reg(struct fh_aes_dev *dev, uint8_t *key,
+ uint8_t *iv, unsigned int keylen);
+static void fh_unset_indata(struct fh_aes_dev *dev);
+static void fh_unset_outdata(struct fh_aes_dev *dev);
+static void fh_aes_complete(struct fh_aes_dev *dev, int err);
+static void fh_aes_crypt_start(struct fh_aes_dev *dev, unsigned long mode);
+static void fh_aes_work_cb(struct work_struct *w);
+static void fh_aes_crypt_with_sg(struct fh_aes_dev *dev,
+unsigned long mode, struct crypto_tfm *tfm);
+#define fh_des_setkey fh_aes_setkey
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+struct fh_aes_dev *pobj_aes_dev = NULL;
+static struct crypto_alg algs[] = {
+ {
+
+ .cra_name = "ecb(aes)",
+ .cra_driver_name = "ecb-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_ecb_encrypt,
+ .decrypt = fh_aes_ecb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_cbc_encrypt,
+ .decrypt = fh_aes_cbc_decrypt,
+ }
+ },
+ {
+ .cra_name = "ctr(aes)",
+ .cra_driver_name = "ctr-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_ctr_encrypt,
+ .decrypt = fh_aes_ctr_decrypt,
+ }
+ },
+ {
+ .cra_name = "ofb(aes)",
+ .cra_driver_name = "ofb-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_ofb_encrypt,
+ .decrypt = fh_aes_ofb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cfb(aes)",
+ .cra_driver_name = "cfb-aes-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = fh_aes_setkey,
+ .encrypt = fh_aes_cfb_encrypt,
+ .decrypt = fh_aes_cfb_decrypt,
+ }
+ },
+ {
+ .cra_name = "ecb(des)",
+ .cra_driver_name = "ecb-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_ecb_encrypt,
+ .decrypt = fh_des_ecb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cbc(des)",
+ .cra_driver_name = "cbc-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_cbc_encrypt,
+ .decrypt = fh_des_cbc_decrypt,
+ }
+ },
+ {
+ .cra_name = "ofb(des)",
+ .cra_driver_name = "ofb-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_ofb_encrypt,
+ .decrypt = fh_des_ofb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cfb(des)",
+ .cra_driver_name = "cfb-des-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .ivsize = DES_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_cfb_encrypt,
+ .decrypt = fh_des_cfb_decrypt,
+ }
+ },
+ {
+ .cra_name = "ecb(des3)",
+ .cra_driver_name = "ecb-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_ecb_encrypt,
+ .decrypt = fh_des_tri_ecb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cbc(des3)",
+ .cra_driver_name = "cbc-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_cbc_encrypt,
+ .decrypt = fh_des_tri_cbc_decrypt,
+ }
+ },
+ {
+ .cra_name = "ofb(des3)",
+ .cra_driver_name = "ofb-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_ofb_encrypt,
+ .decrypt = fh_des_tri_ofb_decrypt,
+ }
+ },
+ {
+ .cra_name = "cfb(des3)",
+ .cra_driver_name = "cfb-des3-fh",
+ .cra_priority = 100,
+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC,
+ .cra_blocksize = DES3_EDE_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct fh_aes_ctx),
+ .cra_alignmask = 0x0f,
+ .cra_type = &crypto_ablkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = fh_aes_cra_init,
+ .cra_u.ablkcipher = {
+ .min_keysize = DES3_EDE_KEY_SIZE,
+ .max_keysize = DES3_EDE_KEY_SIZE,
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .setkey = fh_des_setkey,
+ .encrypt = fh_des_tri_cfb_encrypt,
+ .decrypt = fh_des_tri_cfb_decrypt,
+ }
+ },
+
+};
+
+
+
+
+#ifdef CONFIG_FH_AES_SELF_TEST
+extern void fh_aes_self_test_all(void);
+static int fh_aes_test_func(void *arg)
+{
+ pr_info("%s\n", __func__);
+
+ msleep(10000);
+
+ fh_aes_self_test_all();
+ return 0;
+}
+#endif
+
+static unsigned int get_tfm_block_size(struct crypto_tfm *tfm)
+{
+ return tfm->__crt_alg->cra_blocksize;
+}
+/* function body */
+static int fh_aes_handle_req(struct fh_aes_dev *dev,
+ struct ablkcipher_request *req)
+{
+ unsigned long flags;
+ int err;
+ //*(int *)0 = 1;
+ //BUG();
+ spin_lock_irqsave(&dev->lock, flags);
+
+ err = ablkcipher_enqueue_request(&dev->queue, req);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ queue_work(dev->workqueue, &dev->work);
+
+ return err;
+}
+
+static int fh_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
+{
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ struct fh_aes_reqctx *reqctx = ablkcipher_request_ctx(req);
+ struct fh_aes_dev *dev = ctx->dev;
+ AES_DBG("%s\n", __func__);
+ dev->reqctx = reqctx;
+ /*if (!(mode & CFB_MODE)) {*/
+ if ((!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE))
+ && (!IS_ALIGNED(req->nbytes, DES_BLOCK_SIZE))) {
+ pr_err("request size is not exact amount of AES blocks\n");
+ return -EINVAL;
+ }
+ /*}*/
+ AES_DBG("reqctx->mode value: %x\n", (unsigned int)mode);
+ reqctx->mode = mode;
+
+ return fh_aes_handle_req(dev, req);
+}
+
+static int fh_aes_ecb_encrypt(struct ablkcipher_request *req)
+{
+
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 method = 0;
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT);
+}
+
+
+static int fh_aes_ecb_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT);
+}
+
+static int fh_aes_cbc_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+ struct fh_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ u32 method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT);
+}
+
+static int fh_aes_cbc_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT);
+}
+
+static int fh_aes_ctr_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | CTR_MODE | ENCRYPT);
+}
+
+static int fh_aes_ctr_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | CTR_MODE | DECRYPT);
+}
+
+static int fh_aes_ofb_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT);
+}
+
+static int fh_aes_ofb_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT);
+}
+
+static int fh_aes_cfb_encrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT);
+}
+
+static int fh_aes_cfb_decrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *tfm;
+ struct fh_aes_ctx *ctx;
+ u32 method;
+
+ tfm = crypto_ablkcipher_reqtfm(req);
+ ctx = crypto_ablkcipher_ctx(tfm);
+ method = 0;
+
+ AES_DBG("%s\n", __func__);
+ switch (ctx->keylen) {
+ case AES_KEYSIZE_128:
+ method = AES_128_METHOD;
+ break;
+ case AES_KEYSIZE_192:
+ method = AES_192_METHOD;
+ break;
+ case AES_KEYSIZE_256:
+ method = AES_256_METHOD;
+ break;
+ default:
+ break;
+ }
+
+ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT);
+}
+static int fh_des_ecb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT);
+}
+
+static int fh_des_ecb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT);
+}
+
+static int fh_des_cbc_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT);
+}
+
+static int fh_des_cbc_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT);
+}
+
+static int fh_des_ofb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT);
+}
+
+static int fh_des_ofb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT);
+}
+
+static int fh_des_cfb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT);
+}
+
+static int fh_des_cfb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = DES_METHOD;
+
+ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT);
+}
+static int fh_des_tri_ecb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | ECB_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_ecb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | ECB_MODE | DECRYPT);
+}
+
+static int fh_des_tri_cbc_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CBC_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_cbc_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CBC_MODE | DECRYPT);
+}
+
+static int fh_des_tri_ofb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | OFB_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_ofb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | OFB_MODE | DECRYPT);
+}
+
+static int fh_des_tri_cfb_encrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CFB_MODE | ENCRYPT);
+}
+
+static int fh_des_tri_cfb_decrypt(struct ablkcipher_request *req)
+{
+ u32 method;
+ method = 0;
+ method = TRIPLE_DES_METHOD;
+ return fh_aes_crypt(req, method | CFB_MODE | DECRYPT);
+}
+static int fh_aes_setkey(struct crypto_ablkcipher *cipher, const uint8_t *key,
+ unsigned int keylen)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+ struct fh_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ AES_DBG("%s\n", __func__);
+ if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192
+ && keylen != AES_KEYSIZE_256 && keylen != DES_KEY_SIZE
+ && keylen != DES3_EDE_KEY_SIZE)
+ return -EINVAL;
+
+ memcpy(ctx->aes_key, key, keylen);
+ ctx->keylen = keylen;
+ return 0;
+}
+
+static int fh_aes_cra_init(struct crypto_tfm *tfm)
+{
+ struct fh_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ ctx->dev = pobj_aes_dev;
+ tfm->crt_ablkcipher.reqsize = sizeof(struct fh_aes_reqctx);
+ AES_DBG("%s\n", __func__);
+ return 0;
+}
+
+static void fh_aes_tx(struct fh_aes_dev *dev)
+{
+ /*cpy dri local buf to core sg buf*/
+ unsigned char *dst_xbuf;
+ u32 size = dev->ot_size;
+ u32 cpy_size = 0;
+ u32 i = 0;
+ /* unmap driver buf first.*/
+ fh_unset_outdata(dev);
+ dst_xbuf = &dev->ctl_dst_xbuf[0];
+ do {
+ /*get the sg list offset left
+ and the xfer size lower one.*/
+ cpy_size = min_t(u32,
+ sg_dma_len(dev->sg_dst) - dev->dst_sg_offset, size);
+ sg_pcopy_from_buffer(dev->sg_dst, 1,
+ &dst_xbuf[i], cpy_size, dev->dst_sg_offset);
+ i += cpy_size;
+ dev->dst_sg_offset += cpy_size;
+ size -= cpy_size;
+ if (dev->dst_sg_offset == sg_dma_len(dev->sg_dst)) {
+ /*if sg offset get to the end of sg list.
+ then find the next..*/
+ dev->dst_sg_offset = 0;
+ dev->sg_dst = sg_next(dev->sg_dst);
+ }
+ } while (size);
+
+}
+
+static void fh_aes_rx(struct fh_aes_dev *dev)
+{
+ fh_unset_indata(dev);
+}
+
+static int fh_set_indata(struct fh_aes_dev *dev, struct scatterlist *sg)
+{
+ /*cpy usr buf data to dri local buf*/
+ unsigned char *src_xbuf;
+ int err;
+ u32 cpy_size = 0;
+ u32 i = 0;
+ u32 size = dev->ot_size;
+
+ src_xbuf = &dev->ctl_src_xbuf[0];
+
+ do {
+ /*get the sg list offset left and the xfer size lower one.*/
+ cpy_size = min_t(u32,
+ sg_dma_len(dev->sg_src) - dev->src_sg_offset, size);
+ sg_pcopy_to_buffer(dev->sg_src, 1,
+ &src_xbuf[i], cpy_size, dev->src_sg_offset);
+ i += cpy_size;
+ dev->src_sg_offset += cpy_size;
+ size -= cpy_size;
+ if (dev->src_sg_offset == sg_dma_len(dev->sg_src)) {
+ /*if sg offset get to the end of sg list.
+ then find the next..*/
+ dev->src_sg_offset = 0;
+ dev->sg_src = sg_next(dev->sg_src);
+ }
+ } while (size);
+ /* cpy core date to driver buf, map the driver sg*/
+ sg_init_one(&dev->src_sg_array[0], &src_xbuf[0], dev->ot_size);
+ err = dma_map_sg(dev->dev, &dev->src_sg_array[0], 1, DMA_TO_DEVICE);
+ if (!err)
+ BUG();
+ return err;
+}
+
+static int fh_set_outdata(struct fh_aes_dev *dev, struct scatterlist *sg)
+{
+ int err;
+ /*out data to driver buf, then cpy to core buf*/
+ sg_init_one(&dev->dst_sg_array[0],
+ &dev->ctl_dst_xbuf[0], dev->ot_size);
+ err = dma_map_sg(dev->dev, &dev->dst_sg_array[0], 1, DMA_FROM_DEVICE);
+ if (!err)
+ BUG();
+ return err;
+}
+
+
+static void fh_set_aes_key_reg(struct fh_aes_dev *dev, uint8_t *key,
+ uint8_t *iv, unsigned int keylen)
+{
+ u32 method;
+ u32 key_size = 0;
+ u32 iv_size = 0;
+ void *key_map = NULL;
+
+ if (dev->iv_flag == true) {
+ /*set iv*/
+ /*if aes mode ....set 128 bit iv, des set 64bit iv..*/
+ AES_DBG("set iv reg\n");
+ if ((dev->control_reg & AES_128_METHOD)
+ || ((dev->control_reg & AES_192_METHOD))
+ || (dev->control_reg & AES_256_METHOD)) {
+ AES_DBG("aes iv mode...\n");
+ iv_size = 16;
+ } else {
+ AES_DBG("des iv mode...\n");
+ iv_size = 8;
+ }
+ tee_fh_aes_set_iv(iv, iv_size);
+ }
+ /*set key...*/
+ method = dev->control_reg & 0x0e;
+ AES_DBG("set key reg\n");
+
+ switch (method) {
+ case AES_128_METHOD:
+ AES_DBG("set key aes 128 mode..\n");
+ key_size = 16;
+
+ break;
+ case AES_192_METHOD:
+ AES_DBG("set key aes 192 mode..\n");
+ key_size = 24;
+ break;
+
+ case AES_256_METHOD:
+ AES_DBG("set key aes 256 mode..\n");
+ key_size = 32;
+ break;
+
+ case DES_METHOD:
+ AES_DBG("set key des normal mode..\n");
+ key_size = 8;
+ break;
+
+ case TRIPLE_DES_METHOD:
+ AES_DBG("set key des triple mode..\n");
+ key_size = 24;
+ break;
+
+ default:
+ AES_DBG("error method!!\n");
+ break;
+ }
+
+ if (dev->p_usr_def->mode & CRYPTO_EX_MEM_SWITCH_KEY)
+ key_map = &dev->p_usr_def->adv.ex_key_para;
+ else
+ key_map = NULL;
+ /* printk("usr def data is %x\n",dev->p_usr_def->mode); */
+ tee_fh_aes_set_key(key, key_map, key_size);
+}
+
+static void fh_unset_indata(struct fh_aes_dev *dev)
+{
+ dma_unmap_sg(dev->dev, &dev->src_sg_array[0], 1, DMA_TO_DEVICE);
+}
+
+static void fh_unset_outdata(struct fh_aes_dev *dev)
+{
+ dma_unmap_sg(dev->dev, &dev->dst_sg_array[0], 1, DMA_FROM_DEVICE);
+}
+
+static void fh_aes_complete(struct fh_aes_dev *dev, int err)
+{
+ if (dev->req->base.complete)
+ dev->req->base.complete(&dev->req->base, err);
+}
+
+enum {
+ CRYPT_TYPE_AES,
+ CRYPT_TYPE_DES,
+ CRYPT_TYPE_DES3,
+};
+
+static void fh_aes_crypt_start(struct fh_aes_dev *dev,
+unsigned long mode)
+{
+ struct crypto_tfm *tfm;
+ struct crypto_ablkcipher *p_tfm;
+ struct ablkcipher_request *req;
+
+ req = dev->req;
+ p_tfm = crypto_ablkcipher_reqtfm(dev->req);
+ tfm = crypto_ablkcipher_tfm(p_tfm);
+ fh_aes_crypt_with_sg(dev, mode, tfm);
+
+ return;
+
+}
+
+static u32 fh_aes_update_request_data_size(u32 max_xfer_size,
+u32 *total_size, u32 *first)
+{
+ u32 step_size = 0;
+
+ step_size = min_t(u32, *total_size, max_xfer_size);
+ if (*first == 0)
+ *first = 1;
+
+ *total_size -= step_size;
+ return step_size;
+}
+
+static void fh_aes_crypt_with_sg(struct fh_aes_dev *dev,
+ unsigned long mode, struct crypto_tfm *tfm)
+{
+ struct ablkcipher_request *req = dev->req;
+ u32 control_reg = 0;
+ int err;
+ int crypto_type, crypto_mode;
+
+ u32 total_size;
+ u32 block_size_limit;
+ u32 ot_len;
+ u32 first_in = 0;
+
+ total_size = req->nbytes;
+ block_size_limit = get_tfm_block_size(tfm);
+ dev->sg_src = req->src;
+ dev->sg_dst = req->dst;
+ dev->src_sg_offset = 0;
+ dev->dst_sg_offset = 0;
+
+ err = tee_open_session(&ctx, &sess, &TA_FH_AES_UUID);
+ if (err) {
+ pr_err("open_session failed: %d\n", err);
+ return;
+ }
+
+ while (total_size) {
+ if (((mode & CBC_MODE) || (mode & CTR_MODE) || (mode & CFB_MODE)
+ || (mode & OFB_MODE)) && (first_in == 0)) {
+ control_reg |= 1 << 7;
+ dev->iv_flag = true;
+ } else {
+ control_reg &= ~(1 << 7);
+ dev->iv_flag = false;
+ }
+
+ /*emode & method*/
+ control_reg |= (unsigned int) mode;
+ dev->control_reg = control_reg;
+
+ crypto_mode = (mode & 0x7 << EMODE_POS);
+ crypto_type = mode & 0x0e;
+ if (crypto_type == DES_METHOD)
+ crypto_type = CRYPT_TYPE_DES;
+ else if (crypto_type == TRIPLE_DES_METHOD)
+ crypto_type = CRYPT_TYPE_DES3;
+ else
+ crypto_type = CRYPT_TYPE_AES;
+
+ if (first_in == 0) {
+ tee_fh_aes_prepare(crypto_type, crypto_mode, dev->p_usr_def->mode);
+ fh_set_aes_key_reg(dev, dev->ctx->aes_key, req->info, dev->ctx->keylen);
+ tee_fh_aes_start_transfer();
+ }
+
+ ot_len = fh_aes_update_request_data_size(
+ FH_AES_CTL_MAX_PROCESS_SIZE, &total_size, &first_in);
+ if (ot_len % block_size_limit)
+ BUG();
+ dev->ot_size = ot_len;
+
+ fh_set_indata(dev, &dev->src_sg_array[0]);
+ fh_set_outdata(dev, &dev->dst_sg_array[0]);
+
+ if ((mode & 0x1) == 0)
+ err = tee_fh_aes_encrypt(dev->ctl_src_xbuf, dev->ctl_dst_xbuf, ot_len);
+ else
+ err = tee_fh_aes_decrypt(dev->ctl_src_xbuf, dev->ctl_dst_xbuf, ot_len);
+ if (err)
+ goto error;
+
+ /*update dst sg...*/
+ fh_aes_rx(dev);
+ fh_aes_tx(dev);
+ }
+
+error:
+ tee_close_session(&ctx, &sess);
+}
+
+static void fh_aes_work_cb(struct work_struct *w)
+{
+ struct fh_aes_dev *dev = container_of(w, struct fh_aes_dev, work);
+ struct crypto_async_request *async_req, *backlog;
+ struct fh_aes_reqctx *reqctx;
+ struct crypto_ablkcipher *p_tfm;
+ struct af_alg_usr_def *p_usr_def;
+ unsigned long flags;
+ struct ablkcipher_request *p_ablk_req;
+
+ AES_DBG("%s\n", __func__);
+ /*get the req need to handle*/
+ spin_lock_irqsave(&dev->lock, flags);
+ async_req = crypto_dequeue_request(&dev->queue);
+ backlog = crypto_get_backlog(&dev->queue);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ if (!async_req)
+ return;
+
+ dev->req = ablkcipher_request_cast(async_req);
+ p_tfm = crypto_ablkcipher_reqtfm(dev->req);
+ p_ablk_req = dev->req;
+ p_usr_def = p_ablk_req->usr_def;
+ //p_usr_def = crypto_ablkcipher_usr_def(p_tfm);
+ dev->p_usr_def = p_usr_def;
+ dev->ctx = crypto_tfm_ctx(dev->req->base.tfm);
+ reqctx = ablkcipher_request_ctx(dev->req);
+ fh_aes_crypt_start(dev, reqctx->mode);
+ fh_aes_complete(dev, 0);
+ if (backlog) {
+ if (backlog->complete)
+ backlog->complete(backlog, -EINPROGRESS);
+ }
+ /*call the queue work until empty.*/
+ if (dev->queue.qlen != 0)
+ queue_work(dev->workqueue, &dev->work);
+}
+
+
+int fh_aes_ctl_mem_init(struct fh_aes_dev *pdata)
+{
+ unsigned int t1;
+ unsigned int t2;
+ unsigned int t3;
+ unsigned int t4;
+
+ t1 = (unsigned int)kmalloc(FH_AES_MALLOC_SIZE
+ + FH_AES_ALLIGN_SIZE, GFP_KERNEL);
+ if (!t1)
+ goto err1;
+
+ t2 = (unsigned int)kmalloc(FH_AES_MALLOC_SIZE
+ + FH_AES_ALLIGN_SIZE, GFP_KERNEL);
+ if (!t2)
+ goto err2;
+
+
+ t3 = ((t1 + FH_AES_ALLIGN_SIZE - 1) & (~(FH_AES_ALLIGN_SIZE - 1)));
+ t4 = ((t2 + FH_AES_ALLIGN_SIZE - 1) & (~(FH_AES_ALLIGN_SIZE - 1)));
+
+ pdata->ctl_raw_src_xbuf = (unsigned char *)t1;
+ pdata->ctl_raw_dst_xbuf = (unsigned char *)t2;
+ pdata->ctl_src_xbuf = (unsigned char *)t3;
+ pdata->ctl_dst_xbuf = (unsigned char *)t4;
+ return 0;
+err2:
+ kfree((void *)t1);
+err1:
+ return -1;
+
+}
+
+static int fh_aes_probe(struct platform_device *pdev)
+{
+ int i, j, err = -ENODEV;
+ struct fh_aes_dev *pdata;
+ struct device *dev = &pdev->dev;
+ u32 uuid_array[11];
+ TEEC_UUID uuid;
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+
+ err = of_property_read_u32_array(np, "optee-uuid", uuid_array, 11);
+ if (err) {
+ dev_err(&pdev->dev, "error when parse optee-uuid %s", np->full_name);
+ return err;
+ } else {
+#else
+ void *plat_data = dev_get_platdata(&pdev->dev);
+
+ if (!plat_data) {
+ dev_err(&pdev->dev, "cannot get optee-uuid from plat_data");
+ } else {
+ memcpy(uuid_array, plat_data, sizeof(uuid_array));
+#endif
+
+ uuid = get_uuid_from_array(uuid_array);
+ dev_info(&pdev->dev,
+ "aes-uuid: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.timeLow, uuid.timeMid, uuid.timeHiAndVersion,
+ uuid.clockSeqAndNode[0], uuid.clockSeqAndNode[1],
+ uuid.clockSeqAndNode[2], uuid.clockSeqAndNode[3],
+ uuid.clockSeqAndNode[4], uuid.clockSeqAndNode[5],
+ uuid.clockSeqAndNode[6], uuid.clockSeqAndNode[7]);
+ }
+
+ TA_FH_AES_UUID = uuid;
+
+ pdata = kzalloc(sizeof(struct fh_aes_dev), GFP_KERNEL);
+ if (!pdata) {
+ err = -ENOMEM;
+ goto err_malloc;
+ }
+ spin_lock_init(&pdata->lock);
+
+ pdata->regs = NULL;
+
+ pdata->en_isr = 1 << 0;
+
+ /*bind to plat dev..*/
+ pdata->dev = dev;
+ /*bing to static para..only one aes controller in fh..*/
+ pobj_aes_dev = pdata;
+ platform_set_drvdata(pdev, pdata);
+
+ pdata->workqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
+ if (!pdata->workqueue) {
+ dev_err(&pdev->dev, "aes workqueue init error.\n");
+ goto err_irq;
+ }
+ INIT_WORK(&pdata->work, fh_aes_work_cb);
+ crypto_init_queue(&pdata->queue, CRYPTO_QUEUE_LEN);
+ for (i = 0; i < ARRAY_SIZE(algs); i++) {
+ INIT_LIST_HEAD(&algs[i].cra_list);
+ err = crypto_register_alg(&algs[i]);
+
+ if (err) {
+ dev_warn(dev, "register alg error...\n");
+ goto err_algs;
+ }
+ }
+
+ err = fh_aes_ctl_mem_init(pdata);
+ if (err) {
+ dev_err(&pdev->dev, "aes malloc mem error..\n");
+ goto err_algs;
+ }
+ dev_info(&pdev->dev, "aes driver registered\n");
+
+
+#ifdef CONFIG_FH_AES_SELF_TEST
+#include <linux/kthread.h>
+ kthread_run(fh_aes_test_func, NULL, "aes_self_test");
+#endif
+
+ return 0;
+err_algs:
+ for (j = 0; j < i; j++)
+ crypto_unregister_alg(&algs[j]);
+ destroy_workqueue(pdata->workqueue);
+ platform_set_drvdata(pdev, NULL);
+ pobj_aes_dev = NULL;
+
+err_irq:
+ kfree(pdata);
+err_malloc:
+ pr_info("%s %d\n", __func__, __LINE__);
+
+ return err;
+}
+
+
+static int fh_aes_remove(struct platform_device *pdev)
+{
+ int i;
+ struct fh_aes_dev *pdata = platform_get_drvdata(pdev);
+
+ for (i = 0; i < ARRAY_SIZE(algs); i++)
+ crypto_unregister_alg(&algs[i]);
+
+ destroy_workqueue(pdata->workqueue);
+ platform_set_drvdata(pdev, NULL);
+ pobj_aes_dev = NULL;
+ free_irq(pdata->irq_no, pdata);
+ iounmap(pdata->regs);
+ kfree(pdata->ctl_raw_src_xbuf);
+ kfree(pdata->ctl_raw_dst_xbuf);
+ pdata->ctl_raw_src_xbuf = NULL;
+ pdata->ctl_raw_dst_xbuf = NULL;
+ pdata->ctl_src_xbuf = NULL;
+ pdata->ctl_dst_xbuf = NULL;
+ kfree(pdata);
+
+ return 0;
+}
+
+static const struct of_device_id fh_aes_of_match[] = {
+ {.compatible = "fh,fh-aes",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_aes_of_match);
+
+static struct platform_driver fh_aes_driver = {
+ .driver = {
+ .name = "fh_aes",
+ .of_match_table = fh_aes_of_match,
+ },
+ .probe = fh_aes_probe,
+ .remove = fh_aes_remove,
+};
+
+module_platform_driver(fh_aes_driver);
+MODULE_AUTHOR("FULLHAN");
+MODULE_DESCRIPTION("fullhan AES device driver for tee");
+MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/fh_aes_test.c b/drivers/crypto/fh_aes_test.c
new file mode 100644
index 00000000..0988ec32
--- /dev/null
+++ b/drivers/crypto/fh_aes_test.c
@@ -0,0 +1,1448 @@
+/*
+ * fh_aes_test.c
+ *
+ * Created on: May 7, 2015
+ * Author: yu.zhang
+ */
+#ifdef CONFIG_FH_AES_SELF_TEST
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/highmem.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irqreturn.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <crypto/hash.h>
+#include <crypto/cryptd.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <crypto/rng.h>
+#include "fh_aes.h"
+//cbc aes 128
+#define AES_IV0 0x00010203
+#define AES_IV1 0x04050607
+#define AES_IV2 0x08090a0b
+#define AES_IV3 0x0c0d0e0f
+
+#define AES_KEY0 0x2b7e1516
+#define AES_KEY1 0x28aed2a6
+#define AES_KEY2 0xabf71588
+#define AES_KEY3 0x09cf4f3c
+
+
+static const unsigned char aes_cbc_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_cbc_key_buf[] = {
+ 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
+};
+
+
+//ecb aes 256
+#define AES_ECB_KEY0 0x603deb10
+#define AES_ECB_KEY1 0x15ca71be
+#define AES_ECB_KEY2 0x2b73aef0
+#define AES_ECB_KEY3 0x857d7781
+#define AES_ECB_KEY4 0x1f352c07
+#define AES_ECB_KEY5 0x3b6108d7
+#define AES_ECB_KEY6 0x2d9810a3
+#define AES_ECB_KEY7 0x0914dff4
+
+
+static const unsigned char aes_ecb_key_buf[] = {
+ 0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
+ 0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
+};
+
+//ctr aes 192
+#define AES_CTR_KEY0 0x8e73b0f7
+#define AES_CTR_KEY1 0xda0e6452
+#define AES_CTR_KEY2 0xc810f32b
+#define AES_CTR_KEY3 0x809079e5
+#define AES_CTR_KEY4 0x62f8ead2
+#define AES_CTR_KEY5 0x522c6b7b
+
+#define AES_CTR_IV0 0xf0f1f2f3
+#define AES_CTR_IV1 0xf4f5f6f7
+#define AES_CTR_IV2 0xf8f9fafb
+#define AES_CTR_IV3 0xfcfdfeff
+
+
+static const unsigned char aes_ctr_iv_buf[] = {
+ 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
+};
+
+static const unsigned char aes_ctr_key_buf[] = {
+ 0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
+ 0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
+};
+
+
+//ofb aes 256
+#define AES_OFB_256_KEY0 0x603deb10
+#define AES_OFB_256_KEY1 0x15ca71be
+#define AES_OFB_256_KEY2 0x2b73aef0
+#define AES_OFB_256_KEY3 0x857d7781
+#define AES_OFB_256_KEY4 0x1f352c07
+#define AES_OFB_256_KEY5 0x3b6108d7
+#define AES_OFB_256_KEY6 0x2d9810a3
+#define AES_OFB_256_KEY7 0x0914dff4
+
+#define AES_OFB_IV0 0x00010203
+#define AES_OFB_IV1 0x04050607
+#define AES_OFB_IV2 0x08090a0b
+#define AES_OFB_IV3 0x0c0d0e0f
+
+static const unsigned char aes_ofb_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_ofb_key_buf[] = {
+ 0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
+ 0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
+};
+
+//des ecb
+#define DES_ECB_KEY0 0x01010101
+#define DES_ECB_KEY1 0x01010101
+
+static const unsigned char des_ecb_key_buf[] = {
+ 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,
+};
+//des cbc
+#define DES_CBC_KEY0 0x01234567
+#define DES_CBC_KEY1 0x89abcdef
+
+#define DES_CBC_IV0 0x12345678
+#define DES_CBC_IV1 0x90abcdef
+
+
+static const unsigned char des_cbc_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_cbc_iv_buf[] = {
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+
+
+//ofb cbc
+#define DES_OFB_KEY0 0x01234567
+#define DES_OFB_KEY1 0x89abcdef
+
+#define DES_OFB_IV0 0x12345678
+#define DES_OFB_IV1 0x90abcdef
+
+static const unsigned char des_ofb_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_ofb_iv_buf[] = {
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+
+//ecb tri-des
+#define DES_TRI_ECB_KEY0 0x01234567
+#define DES_TRI_ECB_KEY1 0x89abcdef
+
+#define DES_TRI_ECB_KEY2 0x23456789
+#define DES_TRI_ECB_KEY3 0xabcdef01
+
+#define DES_TRI_ECB_KEY4 0x456789ab
+#define DES_TRI_ECB_KEY5 0xcdef0123
+
+static const unsigned char des3_ecb_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
+ 0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
+};
+
+//cbc tri-des
+#define DES_TRI_CBC_KEY0 0x01234567
+#define DES_TRI_CBC_KEY1 0x89abcdef
+
+#define DES_TRI_CBC_KEY2 0x23456789
+#define DES_TRI_CBC_KEY3 0xabcdef01
+
+#define DES_TRI_CBC_KEY4 0x456789ab
+#define DES_TRI_CBC_KEY5 0xcdef0123
+
+#define DES_TRI_CBC_IV0 0x12345678
+#define DES_TRI_CBC_IV1 0x90abcdef
+
+static const unsigned char des3_cbc_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
+ 0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
+};
+static const unsigned char des3_cbc_iv_buf[] = {
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+#define XBUFSIZE 512
+
+struct tcrypt_result {
+ struct completion completion;
+ int err;
+};
+
+static inline void hexdump(unsigned char *buf, unsigned int len);
+static void tcrypt_complete(struct crypto_async_request *req, int err);
+static int testmgr_alloc_buf(char *buf[XBUFSIZE]);
+
+
+static struct tcrypt_result result;
+static const unsigned char plain_text[] = {
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char cipher_text[] = {
+ 0x76,0x49,0xab,0xac, 0x81,0x19,0xb2,0x46, 0xce,0xe9,0x8e,0x9b, 0x12,0xe9,0x19,0x7d,
+ 0x50,0x86,0xcb,0x9b, 0x50,0x72,0x19,0xee, 0x95,0xdb,0x11,0x3a, 0x91,0x76,0x78,0xb2,
+ 0x73,0xbe,0xd6,0xb8, 0xe3,0xc1,0x74,0x3b, 0x71,0x16,0xe6,0x9e, 0x22,0x22,0x95,0x16,
+ 0x3f,0xf1,0xca,0xa1, 0x68,0x1f,0xac,0x09, 0x12,0x0e,0xca,0x30, 0x75,0x86,0xe1,0xa7,
+};
+
+static const unsigned char plain_ecb_256_text[] = {
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char cipher_ecb_256_text[] = {
+ 0xf3,0xee,0xd1,0xbd, 0xb5,0xd2,0xa0,0x3c, 0x06,0x4b,0x5a,0x7e, 0x3d,0xb1,0x81,0xf8,
+ 0x59,0x1c,0xcb,0x10, 0xd4,0x10,0xed,0x26, 0xdc,0x5b,0xa7,0x4a, 0x31,0x36,0x28,0x70,
+ 0xb6,0xed,0x21,0xb9, 0x9c,0xa6,0xf4,0xf9, 0xf1,0x53,0xe7,0xb1, 0xbe,0xaf,0xed,0x1d,
+ 0x23,0x30,0x4b,0x7a, 0x39,0xf9,0xf3,0xff, 0x06,0x7d,0x8d,0x8f, 0x9e,0x24,0xec,0xc7,
+};
+
+static const unsigned char plain_ctr_192_text[] = {
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char cipher_ctr_192_text[] = {
+ 0x1a,0xbc,0x93,0x24, 0x17,0x52,0x1c,0xa2, 0x4f,0x2b,0x04,0x59, 0xfe,0x7e,0x6e,0x0b,
+ 0x09,0x03,0x39,0xec, 0x0a,0xa6,0xfa,0xef, 0xd5,0xcc,0xc2,0xc6, 0xf4,0xce,0x8e,0x94,
+ 0x1e,0x36,0xb2,0x6b, 0xd1,0xeb,0xc6,0x70, 0xd1,0xbd,0x1d,0x66, 0x56,0x20,0xab,0xf7,
+ 0x4f,0x78,0xa7,0xf6, 0xd2,0x98,0x09,0x58, 0x5a,0x97,0xda,0xec, 0x58,0xc6,0xb0,0x50,
+};
+
+static const unsigned char plain_ofb_256_text[] = {
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char cipher_ofb_256_text[] = {
+ 0xdc,0x7e,0x84,0xbf,0xda,0x79,0x16,0x4b,0x7e,0xcd,0x84,0x86,0x98,0x5d,0x38,0x60,
+ 0x4f,0xeb,0xdc,0x67,0x40,0xd2,0x0b,0x3a,0xc8,0x8f,0x6a,0xd8,0x2a,0x4f,0xb0,0x8d,
+ 0x71,0xab,0x47,0xa0,0x86,0xe8,0x6e,0xed,0xf3,0x9d,0x1c,0x5b,0xba,0x97,0xc4,0x08,
+ 0x01,0x26,0x14,0x1d,0x67,0xf3,0x7b,0xe8,0x53,0x8f,0x5a,0x8b,0xe7,0x40,0xe4,0x84,
+};
+
+static const unsigned char plain_des_ecb_text[] = {
+ 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const unsigned char cipher_des_ecb_text[] = {
+ 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00,0xDD,0x7F,0x12,0x1C,0xA5,0x01,0x56,0x19,
+ 0x2E,0x86,0x53,0x10,0x4F,0x38,0x34,0xEA,0x4B,0xD3,0x88,0xFF,0x6C,0xD8,0x1D,0x4F,
+ 0x20,0xB9,0xE7,0x67,0xB2,0xFB,0x14,0x56,0x55,0x57,0x93,0x80,0xD7,0x71,0x38,0xEF,
+ 0x6C,0xC5,0xDE,0xFA,0xAF,0x04,0x51,0x2F,0x0D,0x9F,0x27,0x9B,0xA5,0xD8,0x72,0x60,
+};
+
+static const unsigned char plain_des_cbc_text[] = {
+ 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
+ 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20,
+};
+
+static const unsigned char cipher_des_cbc_text[] = {
+ 0xe5,0xc7,0xcd,0xde,0x87,0x2b,0xf2,0x7c,0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char plain_des_ofb_text[] = {
+ 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char cipher_des_ofb_text[] = {
+ 0xf3,0x09,0x62,0x49,0xc7,0xf4,0x6e,0x51,0x1e,0x7e,0x5e,0x50,0xcb,0xbe,0xc4,0x10,
+ 0x33,0x35,0xa1,0x8a,0xde,0x4a,0x91,0x15,
+};
+
+static const unsigned char plain_des_tri_ecb_text[] = {
+ 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char cipher_des_tri_ecb_text[] = {
+ 0x31,0x4f,0x83,0x27,0xfa,0x7a,0x09,0xa8,0xd5,0x89,0x5f,0xad,0xe9,0x8f,0xae,0xdf,
+ 0x98,0xf4,0x70,0xeb,0x35,0x53,0xa5,0xda,
+};
+
+static const unsigned char plain_des_tri_cbc_text[] = {
+ 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char cipher_des_tri_cbc_text[] = {
+ 0xf3,0xc0,0xff,0x02,0x6c,0x02,0x30,0x89,0xc4,0x3a,0xdd,0x8f,0xd8,0xcd,0x5e,0x43,
+ 0x2b,0xfd,0x41,0xd3,0x13,0x0b,0xcf,0x40,
+};
+
+static inline void hexdump(unsigned char *buf, unsigned int len)
+{
+ while (len--)
+ AES_DBG("%02x", *buf++);
+ AES_DBG("\n");
+}
+
+static void tcrypt_complete(struct crypto_async_request *req, int err)
+{
+ struct tcrypt_result *res = req->data;
+ if (err == -EINPROGRESS)
+ return;
+
+ AES_DBG("crypt all over....\n");
+ complete(&res->completion);
+
+}
+
+static int testmgr_alloc_buf(char *buf[XBUFSIZE])
+{
+ int i;
+ for (i = 0; i < XBUFSIZE; i++) {
+ buf[i] = (void *)__get_free_page(GFP_KERNEL);
+ if (!buf[i])
+ goto err_free_buf;
+ }
+
+ return 0;
+err_free_buf:
+ while (i-- > 0)
+ free_page((unsigned long)buf[i]);
+
+ return -ENOMEM;
+}
+
+void fh_aes_set_crypto_key_source(struct af_alg_usr_def *p_def, u32 key_source){
+ p_def->mode = key_source;
+}
+
+static int fh_aes_cbc128_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ struct crypto_tfm * t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ const char *algo;
+
+ void *data;
+ void *dst_data;
+
+ u32 key[4] = { AES_KEY0, AES_KEY1, AES_KEY2, AES_KEY3 };
+ u32 iv[4] = { AES_IV0, AES_IV1, AES_IV2, AES_IV3 };
+
+ memcpy(&key[0],&aes_cbc_key_buf[0],sizeof(aes_cbc_key_buf));
+ memcpy(&iv[0],&aes_cbc_iv_buf[0],sizeof(aes_cbc_iv_buf));
+
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+ t_crytfm = crypto_alloc_base("cbc-aes-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ pr_info("driver name %s\n",algo);
+ init_completion(&result.completion);
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 16);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, (void *)iv);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, cipher_text, 64))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, (void *)iv);
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_text, 64))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+
+}
+
+static int fh_aes_ecb256_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ const char *algo;
+ struct crypto_tfm * t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ u32 key[8] = {
+ AES_ECB_KEY0, AES_ECB_KEY1, AES_ECB_KEY2, AES_ECB_KEY3,
+ AES_ECB_KEY4, AES_ECB_KEY5, AES_ECB_KEY6, AES_ECB_KEY7
+ };
+ void *data;
+ void *dst_data;
+ memcpy(&key[0],&aes_ecb_key_buf[0],sizeof(aes_ecb_key_buf));
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+ t_crytfm = crypto_alloc_base("ecb-aes-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+
+ AES_DBG(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&result.completion);
+
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 32);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_ecb_256_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, NULL);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, cipher_ecb_256_text, 64))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_ecb_256_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, NULL);
+
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_ecb_256_text, 64))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+
+}
+
+static int fh_aes_ofb256_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ const char *algo;
+ struct crypto_tfm * t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ u32 key[8] = {
+ AES_OFB_256_KEY0, AES_OFB_256_KEY1, AES_OFB_256_KEY2,
+ AES_OFB_256_KEY3,
+ AES_OFB_256_KEY4, AES_OFB_256_KEY5, AES_OFB_256_KEY6,
+ AES_OFB_256_KEY7
+ };
+ u32 iv[4] =
+ { AES_OFB_IV0, AES_OFB_IV1, AES_OFB_IV2, AES_OFB_IV3 };
+
+ void *data;
+ void *dst_data;
+ memcpy(&key[0],&aes_ofb_key_buf[0],sizeof(aes_ofb_key_buf));
+ memcpy(&iv[0],&aes_ofb_iv_buf[0],sizeof(aes_ofb_iv_buf));
+
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+
+ t_crytfm = crypto_alloc_base("ofb-aes-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+
+ AES_DBG(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&result.completion);
+
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 32);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+ //encrypt
+ memcpy(data, plain_ofb_256_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, (void *)iv);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+ wait_for_completion(&result.completion);
+ if (memcmp(dst_data, cipher_ofb_256_text, 64))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+ //decrypt
+ memcpy(data, cipher_ofb_256_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, (void *)iv);
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_ofb_256_text, 64))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+}
+
+static int fh_des_ecb_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ const char *algo;
+ struct crypto_tfm * t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ u32 key[2] = { DES_ECB_KEY0, DES_ECB_KEY1 };
+
+ void *data;
+ void *dst_data;
+
+ memcpy(&key[0],&des_ecb_key_buf[0],sizeof(des_ecb_key_buf));
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+
+ t_crytfm = crypto_alloc_base("ecb-des-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+
+
+ AES_DBG(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&result.completion);
+
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 8);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_des_ecb_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, NULL);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, cipher_des_ecb_text, 64))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_des_ecb_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, NULL);
+
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_des_ecb_text, 64))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+
+}
+
+static int fh_des_cbc_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ const char *algo;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ struct crypto_tfm * t_crytfm;
+ u32 key[2] = { DES_CBC_KEY0, DES_CBC_KEY1 };
+ u32 iv[2] = { DES_CBC_IV0, DES_CBC_IV1 };
+ void *data;
+ void *dst_data;
+
+
+ memcpy(&key[0],&des_cbc_key_buf[0],sizeof(des_cbc_key_buf));
+ memcpy(&iv[0],&des_cbc_iv_buf[0],sizeof(des_cbc_iv_buf));
+
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+
+ t_crytfm = crypto_alloc_base("cbc-des-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+
+
+ AES_DBG(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&result.completion);
+
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 8);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_des_cbc_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)iv);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, cipher_des_cbc_text, 24))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_des_cbc_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)iv);
+
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_des_cbc_text, 24))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+}
+
+static int fh_des_ofb_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ const char *algo;
+ struct crypto_tfm * t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ u32 key[2] = { DES_OFB_KEY0, DES_OFB_KEY1 };
+ u32 iv[2] = { DES_OFB_IV0, DES_OFB_IV1 };
+ void *data;
+ void *dst_data;
+
+ memcpy(&key[0],&des_ofb_key_buf[0],sizeof(des_ofb_key_buf));
+ memcpy(&iv[0],&des_ofb_iv_buf[0],sizeof(des_ofb_iv_buf));
+
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+
+ t_crytfm = crypto_alloc_base("ofb-des-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+
+ AES_DBG(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&result.completion);
+
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 8);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_des_ofb_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)iv);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+ wait_for_completion(&result.completion);
+ if (memcmp(dst_data, cipher_des_ofb_text, 24))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_des_ofb_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)iv);
+
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+ wait_for_completion(&result.completion);
+ if (memcmp(dst_data, plain_des_ofb_text, 24))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+
+}
+
+static int fh_des_tri_ecb_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ const char *algo;
+ struct crypto_tfm * t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ u32 key[6] = {
+ DES_TRI_ECB_KEY0, DES_TRI_ECB_KEY1, DES_TRI_ECB_KEY2,
+ DES_TRI_ECB_KEY3, DES_TRI_ECB_KEY4, DES_TRI_ECB_KEY5
+ };
+
+ void *data;
+ void *dst_data;
+
+ memcpy(&key[0],&des3_ecb_key_buf[0],sizeof(des3_ecb_key_buf));
+
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+
+ t_crytfm = crypto_alloc_base("ecb-des3-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+
+ AES_DBG(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&result.completion);
+
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 24);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_des_tri_ecb_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)NULL);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, cipher_des_tri_ecb_text, 24))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_des_tri_ecb_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)NULL);
+
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_des_tri_ecb_text, 24))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+
+}
+
+static int fh_des_tri_cbc_self_test(void * xbuf, void* dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ const char *algo;
+ struct crypto_tfm * t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ u32 key[6] = {
+ DES_TRI_CBC_KEY0, DES_TRI_CBC_KEY1, DES_TRI_CBC_KEY2,
+ DES_TRI_CBC_KEY3, DES_TRI_CBC_KEY4, DES_TRI_CBC_KEY5
+ };
+ u32 iv[2] = { DES_TRI_CBC_IV0, DES_TRI_CBC_IV1 };
+
+ void *data;
+ void *dst_data;
+
+
+ memcpy(&key[0],&des3_cbc_key_buf[0],sizeof(des3_cbc_key_buf));
+ memcpy(&iv[0],&des3_cbc_iv_buf[0],sizeof(des3_cbc_iv_buf));
+
+ AES_DBG("aes self test get in...\n");
+
+ AES_DBG(" *_* step 1\n");
+
+
+ t_crytfm = crypto_alloc_base("cbc-des3-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+
+
+ AES_DBG(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&result.completion);
+
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 24);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_des_tri_cbc_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)iv);
+ fh_aes_set_crypto_key_source(p_def, CRYPTO_CPU_SET_KEY);
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, cipher_des_tri_cbc_text, 24))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_des_tri_cbc_text, 24);
+ memset(dst_data, 0, 24);
+ sg_init_one(&sg[0], data, 24);
+ sg_init_one(&dst_sg[0], dst_data, 24);
+
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 24, (void *)iv);
+
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_des_tri_cbc_text, 24))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+
+}
+
+#if(0)
+
+typedef struct
+{
+ unsigned int base;
+ void * vbase;
+ unsigned int size;
+}MEM_INFO;
+typedef struct {
+ MEM_INFO mem;
+ unsigned char *remap_base; /**<已用大小*/
+} RW_MEM_INFO;
+
+
+static unsigned char aes_128_key_buf[] = {
+ 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
+};
+static unsigned char plain_aes_128_text[] = {
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static unsigned char cipher_aes_128_text[] = {
+ 0x3A,0xD7,0x7B,0xB4, 0x0D,0x7A,0x36,0x60, 0xA8,0x9E,0xCA,0xF3, 0x24,0x66,0xEF,0x97,
+ 0xf5,0xd3,0xd5,0x85, 0x03,0xb9,0x69,0x9d, 0xe7,0x85,0x89,0x5a, 0x96,0xfd,0xba,0xaf,
+ 0x43,0xb1,0xcd,0x7f, 0x59,0x8e,0xce,0x23, 0x88,0x1b,0x00,0xe3, 0xed,0x03,0x06,0x88,
+ 0x7b,0x0c,0x78,0x5e, 0x27,0xe8,0xad,0x3f, 0x82,0x23,0x20,0x71, 0x04,0x72,0x5d,0xd4,
+};
+
+int aes_128_ecb_encrypt(char *key_128, RW_MEM_INFO in,
+ RW_MEM_INFO out, unsigned int data_len_align16){
+
+ static char *xbuf;
+ static char *dst_xbuf;
+ static struct crypto_ablkcipher *tfm;
+ static struct ablkcipher_request *req;
+ static malloc_flag = 0;
+ const char *algo;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ void *data;
+ void *dst_data;
+ struct tcrypt_result wait_result;
+
+//malloc buf...
+ if(malloc_flag != 0){
+ goto work_go;
+ }
+ malloc_flag = 1;
+ xbuf = (void *)__get_free_page(GFP_KERNEL);
+ if (!xbuf) {
+ printk("no pages.\n");
+ return -1;
+ }
+
+ dst_xbuf = (void *)__get_free_page(GFP_KERNEL);
+ if (!dst_xbuf) {
+ free_page((unsigned long)xbuf);
+ printk("no pages.\n");
+ return -1;
+ }
+
+ tfm =
+ cryptd_alloc_ablkcipher("ecb-aes-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(tfm)) {
+ printk("aes_test: failed to alloc cipher!\n");
+ free_page((unsigned long)xbuf);
+ free_page((unsigned long)dst_xbuf);
+ return -1;
+ }
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ printk(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+
+work_go:
+ printk("aes self test get in...\n");
+ printk(" *_* step 1\n");
+
+ printk(" *_* step 2\n");
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ init_completion(&wait_result.completion);
+
+ printk(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *)key_128, 16);
+
+ printk(" *_* step 4\n");
+
+
+ printk(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &wait_result);
+
+ printk(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, in.remap_base, data_len_align16);
+ //memset(dst_data, 0, data_len_align16);
+ sg_init_one(&sg[0], data, data_len_align16);
+ sg_init_one(&dst_sg[0], dst_data, data_len_align16);
+
+ printk(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, data_len_align16, NULL);
+
+ printk(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&wait_result.completion);
+
+ memcpy(out.remap_base, dst_data, data_len_align16);
+
+ return 0;
+
+}
+#endif
+
+#if (0)
+/* keymap test with efuse, must set keys in efuse first */
+
+static struct ex_key_map_para ex_key_para = {
+ .map_size = sizeof(aes_cbc_key_buf) / sizeof(uint32_t),
+ .map = { {0, 0}, {1, 4}, {2, 8}, {3, 12} },
+};
+
+static int fh_aes_cbc128_keymap_self_test(void *xbuf, void *dst_xbuf,
+ struct af_alg_usr_def *p_def)
+{
+ struct crypto_ablkcipher *tfm;
+ struct ablkcipher_request *req;
+ struct crypto_tfm *t_crytfm;
+ struct scatterlist sg[8];
+ struct scatterlist dst_sg[8];
+ const char *algo;
+
+ void *data;
+ void *dst_data;
+
+ u32 key[4] = { AES_KEY0, AES_KEY1, AES_KEY2, AES_KEY3 };
+ u32 iv[4] = { AES_IV0, AES_IV1, AES_IV2, AES_IV3 };
+
+ memcpy(&key[0], &aes_cbc_key_buf[0], sizeof(aes_cbc_key_buf));
+ memcpy(&iv[0], &aes_cbc_iv_buf[0], sizeof(aes_cbc_iv_buf));
+
+ AES_DBG("aes self test get in...\n");
+ AES_DBG(" *_* step 1\n");
+ t_crytfm = crypto_alloc_base("cbc-aes-fh",
+ CRYPTO_ALG_TYPE_ABLKCIPHER |
+ CRYPTO_ALG_ASYNC, 0);
+ if (IS_ERR(t_crytfm)) {
+ AES_DBG("aes_test: failed to alloc t_crytfm!\n");
+ return -1;
+ }
+ tfm = __crypto_ablkcipher_cast(t_crytfm);
+ if (IS_ERR(tfm)) {
+ AES_DBG("aes_test: failed to alloc cipher!\n");
+ return -1;
+ }
+ algo = crypto_tfm_alg_driver_name(crypto_ablkcipher_tfm(tfm));
+ pr_info("driver name %s\n", algo);
+ init_completion(&result.completion);
+ AES_DBG(" *_* step 3\n");
+ crypto_ablkcipher_setkey(tfm, (u8 *) key, 16);
+
+ AES_DBG(" *_* step 4\n");
+ req = ablkcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ AES_DBG(KERN_ERR "alg: skcipher: Failed to allocate request "
+ "for %s\n", algo);
+ return -1;
+ }
+
+ AES_DBG(" *_* step 5\n");
+ ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+
+ AES_DBG(" *_* step 6\n");
+ data = xbuf;
+ dst_data = dst_xbuf;
+
+ //encrypt
+ memcpy(data, plain_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+
+ AES_DBG(" *_* step 7\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, (void *)iv);
+
+ ablkcipher_request_set_usrdef(req, p_def);
+ AES_DBG(" *_* step 8\n");
+ crypto_ablkcipher_encrypt(req);
+
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, cipher_text, 64))
+ AES_PRINT_RESULT(" encrypt error....\n");
+ else
+ AES_PRINT_RESULT(" encrypt ok....\n");
+
+ //decrypt
+ memcpy(data, cipher_text, 64);
+ memset(dst_data, 0, 64);
+ sg_init_one(&sg[0], data, 64);
+ sg_init_one(&dst_sg[0], dst_data, 64);
+ AES_DBG(" *_* step 8\n");
+ ablkcipher_request_set_crypt(req, sg, dst_sg, 64, (void *)iv);
+ AES_DBG(" *_* step 9\n");
+ crypto_ablkcipher_decrypt(req);
+ wait_for_completion(&result.completion);
+
+ if (memcmp(dst_data, plain_text, 64))
+ AES_PRINT_RESULT(" decrypt error....\n");
+ else
+ AES_PRINT_RESULT(" decrypt ok....\n");
+
+ return 0;
+}
+#endif
+
+int fh_aes_self_test_all(void)
+{
+
+ static char *xbuf;
+ static char *dst_xbuf;
+ struct af_alg_usr_def usr_def = {0};
+
+ xbuf = (void *)__get_free_page(GFP_KERNEL);
+ if (!xbuf) {
+ printk("no pages.\n");
+ return -1;
+ }
+
+ dst_xbuf = (void *)__get_free_page(GFP_KERNEL);
+ if (!dst_xbuf) {
+ free_page((unsigned long)xbuf);
+ printk("no pages.\n");
+ return -1;
+ }
+
+ pr_info("aes cbc128 self test go...\n");
+ fh_aes_cbc128_self_test(xbuf, dst_xbuf, &usr_def);
+ pr_info("aes ecb256 self test go...\n");
+ fh_aes_ecb256_self_test(xbuf, dst_xbuf, &usr_def);
+ pr_info("aes ofb 256 self test go...\n");
+ fh_aes_ofb256_self_test(xbuf, dst_xbuf, &usr_def);
+ pr_info("des ecb self test go...\n");
+ fh_des_ecb_self_test(xbuf, dst_xbuf, &usr_def);
+ pr_info("des cbc self test go...\n");
+ fh_des_cbc_self_test(xbuf, dst_xbuf, &usr_def);
+ pr_info("des ofb self test go...\n");
+ fh_des_ofb_self_test(xbuf, dst_xbuf, &usr_def);
+ pr_info("des tri ecb self test go...\n");
+ fh_des_tri_ecb_self_test(xbuf, dst_xbuf, &usr_def);
+ pr_info("des tri cbc self test go...\n");
+ fh_des_tri_cbc_self_test(xbuf, dst_xbuf, &usr_def);
+
+#if (0)
+ pr_info("########## fh_aes_cbc128_keymap_self_test ###########\n");
+ usr_def.mode = CRYPTO_EX_MEM_SET_KEY;
+ usr_def.adv.ex_key_para = ex_key_para;
+ fh_aes_cbc128_keymap_self_test(xbuf, dst_xbuf, &usr_def);
+ usr_def.mode = CRYPTO_EX_MEM_SWITCH_KEY | CRYPTO_EX_MEM_4_ENTRY_1_KEY
+ | CRYPTO_EX_MEM_SET_KEY;
+ fh_aes_cbc128_keymap_self_test(xbuf, dst_xbuf, &usr_def);
+#endif
+
+#if (0)
+ RW_MEM_INFO in;
+ RW_MEM_INFO out;
+ unsigned char temp_buf[64] = {0};
+
+ in.remap_base = &plain_aes_128_text[0];
+ out.remap_base = &temp_buf[0];
+
+ pr_info("chenjn self test go.....\n");
+
+ aes_128_ecb_encrypt(&aes_128_key_buf[0], in,
+ out, 64);
+ for (i = 0; i < sizeof(temp_buf); i++)
+ printk("cipher data[%d]:0x%x\n", i, temp_buf[i]);
+#endif
+
+ return 0;
+}
+
+#endif
diff --git a/drivers/cryptodev-linux-master/.gitignore b/drivers/cryptodev-linux-master/.gitignore
new file mode 100644
index 00000000..685e8ebf
--- /dev/null
+++ b/drivers/cryptodev-linux-master/.gitignore
@@ -0,0 +1,29 @@
+.*.cmd
+.tmp_versions/
+*~
+Module.markers
+Module.symvers
+*.ko
+*.o
+*.mod.c
+modules.order
+tests/async_cipher
+tests/async_hmac
+tests/async_speed
+tests/cipher
+tests/cipher_comp
+tests/hmac
+tests/hmac_comp
+tests/speed
+tests/sha_speed
+tests/hash_comp
+tests/hashcrypt_speed
+releases
+scripts
+version.h
+tests/cipher-aead
+tests/fullspeed
+examples/aes
+lib/benchmark
+tests/cipher-aead-srtp
+tests/cipher-gcm
diff --git a/drivers/cryptodev-linux-master/AUTHORS b/drivers/cryptodev-linux-master/AUTHORS
new file mode 100644
index 00000000..6f9408ec
--- /dev/null
+++ b/drivers/cryptodev-linux-master/AUTHORS
@@ -0,0 +1,19 @@
+Michal Ludvig:
+ Initial implementation for linux 2.6.8
+
+Nikos Mavrogiannopoulos:
+ Port to 2.6.27 and later, better compatibility
+ with OpenBSD (and FreeBSD) cryptodev and maintanance.
+
+Michael Weiser:
+ Porting to blkcipher async API. Several hardware drivers
+ only implemented this API.
+
+Phil Sutter:
+ Implemented a zero copy version of the internal engine.
+
+Dmitry Kasatkin:
+ Multi-update support for hash calculation.
+
+
+Maintained by Nikos Mavrogiannopoulos (nmav [at] gnutls [dot] org)
diff --git a/drivers/cryptodev-linux-master/COPYING b/drivers/cryptodev-linux-master/COPYING
new file mode 100644
index 00000000..d159169d
--- /dev/null
+++ b/drivers/cryptodev-linux-master/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/drivers/cryptodev-linux-master/INSTALL b/drivers/cryptodev-linux-master/INSTALL
new file mode 100644
index 00000000..2754c593
--- /dev/null
+++ b/drivers/cryptodev-linux-master/INSTALL
@@ -0,0 +1,32 @@
+=== Installation instructions ===
+
+Simply run:
+$ make
+# make install
+
+The first command compiles the code and generates the kernel module
+and the latter installs the header files and the kernel module.
+
+After that you should set your system to load the kernel module on system
+load. In most systems this can be done as:
+# echo "cryptodev" >>/etc/modules
+
+or in systemd-enabled systems:
+# echo "cryptodev" > /etc/modules-load.d/cryptodev.conf
+
+=== Testing installation ===
+
+* cryptodev-linux:
+Check whether cryptodev-linux is operating as expected using the following
+command.
+$ make check
+
+* OpenSSL:
+run the following commands prior and after installation and compare.
+$ openssl speed -evp aes-128-cbc
+$ openssl speed -evp sha1
+
+* GnuTLS 3.x:
+run the following command prior and after installation and compare.
+$ gnutls-cli --benchmark-ciphers
+
diff --git a/drivers/cryptodev-linux-master/Kconfig b/drivers/cryptodev-linux-master/Kconfig
new file mode 100644
index 00000000..e6c382e9
--- /dev/null
+++ b/drivers/cryptodev-linux-master/Kconfig
@@ -0,0 +1,6 @@
+
+config CRYPTODEV
+tristate "Support cryptodev"
+default n
+help
+ Support \dev\crypto
diff --git a/drivers/cryptodev-linux-master/Makefile b/drivers/cryptodev-linux-master/Makefile
new file mode 100644
index 00000000..6c3bc8ba
--- /dev/null
+++ b/drivers/cryptodev-linux-master/Makefile
@@ -0,0 +1,68 @@
+#
+# Since version 1.6 the asynchronous mode has been
+# disabled by default. To re-enable it uncomment the
+# corresponding CFLAG.
+#
+
+CRYPTODEV_CFLAGS ?= #-DENABLE_ASYNC
+KBUILD_CFLAGS += -I$(src) $(CRYPTODEV_CFLAGS) -Wvla
+KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build
+VERSION = 1.11
+
+prefix ?= /usr/local
+includedir = $(prefix)/include
+
+cryptodev-objs = ioctl.o main.o cryptlib.o authenc.o zc.o util.o
+
+obj-$(CONFIG_CRYPTODEV) += cryptodev.o
+
+KERNEL_MAKE_OPTS := -C $(KERNEL_DIR) M=$(CURDIR)
+ifneq ($(ARCH),)
+KERNEL_MAKE_OPTS += ARCH=$(ARCH)
+endif
+ifneq ($(CROSS_COMPILE),)
+KERNEL_MAKE_OPTS += CROSS_COMPILE=$(CROSS_COMPILE)
+endif
+
+build: version.h
+ $(MAKE) $(KERNEL_MAKE_OPTS) modules
+
+version.h: Makefile
+ @echo "#define VERSION \"$(VERSION)\"" > version.h
+
+install: modules_install
+
+modules_install:
+ $(MAKE) $(KERNEL_MAKE_OPTS) modules_install
+ install -m 644 -D crypto/cryptodev.h $(DESTDIR)/$(includedir)/crypto/cryptodev.h
+
+clean:
+ $(MAKE) $(KERNEL_MAKE_OPTS) clean
+ rm -f $(hostprogs) *~
+ CFLAGS=$(CRYPTODEV_CFLAGS) KERNEL_DIR=$(KERNEL_DIR) $(MAKE) -C tests clean
+
+check:
+ CFLAGS=$(CRYPTODEV_CFLAGS) KERNEL_DIR=$(KERNEL_DIR) $(MAKE) -C tests check
+
+CPOPTS =
+ifneq ($(SHOW_TYPES),)
+CPOPTS += --show-types
+endif
+ifneq ($(IGNORE_TYPES),)
+CPOPTS += --ignore $(IGNORE_TYPES)
+endif
+
+checkpatch:
+ $(KERNEL_DIR)/scripts/checkpatch.pl $(CPOPTS) --file *.c *.h
+
+VERSIONTAG = refs/tags/cryptodev-linux-$(VERSION)
+FILEBASE = cryptodev-linux-$(VERSION)
+OUTPUT = $(FILEBASE).tar.gz
+
+dist: clean
+ @echo Packing
+ @rm -f *.tar.gz
+ @git archive --format=tar.gz --prefix=$(FILEBASE)/ --output=$(OUTPUT) $(VERSIONTAG)
+ @echo Signing $(OUTPUT)
+ @gpg --output $(OUTPUT).sig -sb $(OUTPUT)
+ @gpg --verify $(OUTPUT).sig $(OUTPUT)
diff --git a/drivers/cryptodev-linux-master/NEWS b/drivers/cryptodev-linux-master/NEWS
new file mode 100644
index 00000000..54b58bd6
--- /dev/null
+++ b/drivers/cryptodev-linux-master/NEWS
@@ -0,0 +1,261 @@
+Version 1.11 (released 2020-7-28)
+
+* Fix Module loading with Linux kernel <= 5.0
+* Fix compilation issues against Linux kernel >= 5.5
+* Fix compilation issues against Linux kernel >= 5.8
+* enable support for TLS1.1 - AES128-SHA1 and AES256-SHA1
+* fix cipher-aead-strp dts buffer alignment issue
+* remove VLA usage from authenc.c
+
+Version 1.10 (released 2018-12-20)
+
+* Fix compilation issues against Linux kernel >= 4.11 and gcc >= 5
+* Add CIOCCPHASH ioctl
+* Fix tests build for OpenSSL 1.1
+* Convert to new AEAD kernel crypto interface
+* A variety of bug fixes
+
+Version 1.9 (released 2017-04-22)
+
+* fix benchmarks linking
+
+* fix Makefile to allow parallel make with -j option
+
+* use Linux kernel conventions for Makefile variables
+
+* for consistency, use $(...) instead of ${...} in makefiles
+
+* fix clean-up on error path for crypto_create_session
+
+* remove code duplication in cryptodev_hash_init
+
+* add separate target for building tests
+
+* fix destination for staged installs
+
+* add install target for tests
+
+* fix comment typo
+
+* avoid calls to kmalloc on hotpaths
+
+* avoid redundant checks in cryptodev_hash_deinit
+
+* Fix test compile time warnings
+
+* Support skcipher in addition to ablkcipher API
+
+* Adjust to recent user page API changes
+
+* Adjust to another change in the user page API
+
+* fix issues with install target
+
+* setting KERNEL_DIR is not necessary to build tests
+
+* fix ignored SIGALRM signals on some platforms
+
+* fix incorrect return code in case of error from openssl_cioccrypt
+
+* remove not used local variables
+
+* fix warnings of "implicit declaration of function" in async_speed
+
+* rename header file to clarify purpose
+
+* use buf_align macro to reduce code duplication
+
+* avoid implicit conversion between signed and unsigned char
+
+* do more strict code checking to avoid maintenance issues
+
+* adjust to API changes in kernel >=4.10
+
+* zc: Use the power of #elif
+
+* Fix ablkcipher algorithms usage in v4.8+ kernels
+
+Version 1.8 (released 2015-11-28)
+
+* Fixed compilation against linux-3.19.
+
+* Tests: cixed arg passing to CC in implicit rule.
+
+* Fix tag printing in cipher-gcm test by Fridolin Pokorny.
+
+* Fix compilation against linux 4.3 by Gustavo Zacarias.
+
+Version 1.7 (released 2015-02-07)
+
+* Added support for composite AEAD keys by Cristian Stoica.
+
+* Added support for sysctl to modify verbosity by Nikolaos Tsakalakis.
+
+* Several bugfixes by Cristian Stoica.
+
+* When a driver requires aligned data but unaligned are provided, then
+ zero copy is disabled to prevent driver failing to encrypt.
+
+* Compatibility to kernel version 3.13 and above by Cosmin Paraschiv.
+
+* Various checkpatch.pl fixes.
+
+* Introduced ddebug, dinfo, dwarning and derr macros wrapping dprintk.
+
+* Improved support for cross-compiling.
+
+* Hmac_comp test has become more picky when checking results.
+
+* Fixed allocated resource cleanup in error case, patch by Cristian Stoica.
+
+* Buffer size allocation fixup for AEAD modes by Nikos Mavrogiannopoulos.
+
+* Support for composite AEAD keys added by Cristian Stoica.
+
+* Fixed tag and dsl_len calculation for AEAD ciphers, patch by Cristian Stoica.
+
+* Documentation updates by Nikos Mavrogiannopoulos.
+
+
+Version 1.6 (released 2013-03-20)
+
+* Added modules_install target in Makefile
+
+* Added SHA224. Patch by Yashpal Dutta.
+
+* Asynchronous operations will not be scheduled if zero copy is disabled.
+
+* Asynchronous operations are disabled by default, unless -DENABLE_ASYNC
+ is enabled on Makefile.
+
+
+Version 1.5 (released 2012-08-04)
+
+* Fixes in AEAD support. Patches by Jaren Johnston.
+
+* Simplifications in memory locking. Patch by Phil Sutter.
+
+* Allow empty plaintext and authenticated data in AEAD ciphers.
+ Patch by Jaren Johnston.
+
+
+Version 1.4 (released 2012-03-15)
+
+* Correctly report hw accelerated ciphers.
+
+
+Version 1.3 (released 2012-02-29)
+
+* Return EBADMSG instead of ECANCELED on tag verification failure in
+ authenc modes.
+
+* COP_FLAG_RESET can be combined with COP_FLAG_UPDATE for efficiency.
+
+* Added more test cases.
+
+* Automatically set public permissions for the device
+
+
+Version 1.2 (released 2012-02-24)
+
+* In kernels that do not distinguish between hw accelerated ciphers or
+ not set the SIOP_FLAG_KERNEL_DRIVER_ONLY flag based on driver name.
+
+* camelia was renamed to camellia.
+
+* Added COP_FLAG_RESET to allow resetting the state in multi-update.
+
+* Corrected issue in ARM processors with mv_cesa.
+
+
+Version 1.1 (released 2012-02-20)
+
+* Fixed alignment issue in speed.c
+
+* Defined HASH_MAX_LEN in cryptodev.h
+
+* CIOCGSESSINFO ioctl() sets the SIOP_FLAG_KERNEL_DRIVER_ONLY flag if the
+ driver is only available through kernel driver (and is not just software
+ cipher).
+
+* Added new encryption ioctl, CIOCAUTHCRYPT, which combines authentication
+ and encryption. Operates in AEAD, TLS and SRTP modes (the API might change
+ in later versions).
+
+
+Version 1.0 (released 2011-04-12)
+
+* Several fixes in the included examples. Based on patches by Vladimir
+ Zapolskiy.
+
+
+Version 0.9 (released 2011-02-11)
+
+* Added additional test tools:
+ - sha_speed does performance testing of SHA1 and SHA256
+ - hashcrypt_speed additionally encrypts with AES128 and AES256
+
+* Allow updating the IV in userspace via the COP_FLAG_WRITE_IV flag.
+
+* Export the alignmask in an OCF compatible way.
+
+* Fix for kernel crash on passing incorrect session ID.
+
+* Added CIOCGSESSINFO to export additional information for each session.
+
+
+Version 0.8 (released 2010-11-06)
+
+* Made cryptodev aware of alignment constraints.
+
+* Added support for CRYPTO_AES_ECB.
+
+* Added asynchronous operation support using
+ CIOCASYNCCRYPT, CIOCASYNCFETCH ioctls and poll().
+
+
+Version 0.7 (released 2010-10-08)
+
+* Added COP_FLAG_FINAL to make multi-update more efficient.
+
+* Added CRIOGET_NOT_NEEDED definition to allow users of the API to
+ distinguish from the bare OpenBSD API that requires the CRIOGET.
+
+
+Version 0.6 (released 2010-09-16)
+
+* multi-update support for hash calculation using the new flag
+ COP_FLAG_UPDATE.
+
+* Relicensed under GPLv2.
+
+* Added AES-CTR.
+
+* Corrected fallback to non-zero copy when referenced pages were
+ not writable.
+
+
+Version 0.5 (released 2010-07-06)
+
+* Corrected issue with zero copy on multiple pages.
+
+* Fallback to normal operation if user pages cannot be mapped.
+
+
+Version 0.4 (released 2010-07-03)
+
+* Internal engine supports operations with zero copy from user space.
+
+
+Version 0.3 (released 2010-06-19)
+
+* Corrected bug when initializing unsupported algorithms.
+
+
+Version 0.2 (released 2010-06-18)
+
+* Added compat_ioctl() to allow working on systems where userspace is 32bits
+ and kernel is operating in 64bit mode (Phil Sutter)
+
+* Added several sanity checks to input.
+
diff --git a/drivers/cryptodev-linux-master/README b/drivers/cryptodev-linux-master/README
new file mode 100644
index 00000000..eb192046
--- /dev/null
+++ b/drivers/cryptodev-linux-master/README
@@ -0,0 +1,40 @@
+This is a /dev/crypto device driver, equivalent to those in OpenBSD or
+FreeBSD. The main idea is to access of existing ciphers in kernel space
+from userspace, thus enabling the re-use of a hardware implementation of a
+cipher.
+
+For questions and suggestions please use the mailing lists at:
+http://cryptodev-linux.org/lists.html
+
+
+=== How to combine with cryptographic libraries ===
+
+* GnuTLS:
+
+GnuTLS needs to be compiled with --enable-cryptodev in order to take
+advantage of /dev/crypto. GnuTLS 3.0.14 or later is recommended.
+
+* OpenSSL:
+
+Note that OpenSSL's cryptodev implementation is outdated, and there
+are issues with it. For that we recommend to use the patches
+below, that we have provided to the openssl project.
+
+http://rt.openssl.org/Ticket/Display.html?id=2770&user=guest&pass=guest
+
+After applying the patches you can add cryptodev support by using the
+-DHAVE_CRYPTODEV and -DUSE_CRYPTODEV_DIGESTS flags during compilation.
+Note that the latter flag (digests) may induce a performance penalty
+in some systems.
+
+
+=== Modifying and viewing verbosity at runtime ===
+
+For debugging often the verbosity of the driver needs to be adjusted.
+The sysctl tool can be used for that.
+
+# sysctl ioctl.cryptodev_verbosity
+ioctl.cryptodev_verbosity = 0
+
+# sysctl ioctl.cryptodev_verbosity=3
+ioctl.cryptodev_verbosity = 3
diff --git a/drivers/cryptodev-linux-master/authenc.c b/drivers/cryptodev-linux-master/authenc.c
new file mode 100644
index 00000000..269b826d
--- /dev/null
+++ b/drivers/cryptodev-linux-master/authenc.c
@@ -0,0 +1,850 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2011, 2012 OpenSSL Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * This file handles the AEAD part of /dev/crypto.
+ *
+ */
+
+#include <crypto/hash.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/ioctl.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+#include <linux/pagemap.h>
+#include <linux/poll.h>
+#include <linux/uaccess.h>
+#include <crypto/cryptodev.h>
+#include <crypto/scatterwalk.h>
+#include <linux/scatterlist.h>
+#include "cryptodev_int.h"
+#include "zc.h"
+#include "util.h"
+#include "cryptlib.h"
+#include "version.h"
+
+
+/* make caop->dst available in scatterlist.
+ * (caop->src is assumed to be equal to caop->dst)
+ */
+static int get_userbuf_tls(struct csession *ses, struct kernel_crypt_auth_op *kcaop,
+ struct scatterlist **dst_sg)
+{
+ int pagecount = 0;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ int rc;
+
+ if (caop->dst == NULL)
+ return -EINVAL;
+
+ if (ses->alignmask) {
+ if (!IS_ALIGNED((unsigned long)caop->dst, ses->alignmask + 1))
+ dwarning(2, "careful - source address %p is not %d byte aligned",
+ caop->dst, ses->alignmask + 1);
+ }
+
+ if (kcaop->dst_len == 0) {
+ dwarning(1, "Destination length cannot be zero");
+ return -EINVAL;
+ }
+
+ pagecount = PAGECOUNT(caop->dst, kcaop->dst_len);
+
+ ses->used_pages = pagecount;
+ ses->readonly_pages = 0;
+
+ rc = adjust_sg_array(ses, pagecount);
+ if (rc)
+ return rc;
+
+ rc = __get_userbuf(caop->dst, kcaop->dst_len, 1, pagecount,
+ ses->pages, ses->sg, kcaop->task, kcaop->mm);
+ if (unlikely(rc)) {
+ derr(1, "failed to get user pages for data input");
+ return -EINVAL;
+ }
+
+ (*dst_sg) = ses->sg;
+
+ return 0;
+}
+
+
+#define MAX_SRTP_AUTH_DATA_DIFF 256
+
+/* Makes caop->auth_src available as scatterlist.
+ * It also provides a pointer to caop->dst, which however,
+ * is assumed to be within the caop->auth_src buffer. If not
+ * (if their difference exceeds MAX_SRTP_AUTH_DATA_DIFF) it
+ * returns error.
+ */
+static int get_userbuf_srtp(struct csession *ses, struct kernel_crypt_auth_op *kcaop,
+ struct scatterlist **auth_sg, struct scatterlist **dst_sg)
+{
+ int pagecount, diff;
+ int auth_pagecount = 0;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ int rc;
+
+ if (caop->dst == NULL && caop->auth_src == NULL) {
+ derr(1, "dst and auth_src cannot be both null");
+ return -EINVAL;
+ }
+
+ if (ses->alignmask) {
+ if (!IS_ALIGNED((unsigned long)caop->dst, ses->alignmask + 1))
+ dwarning(2, "careful - source address %p is not %d byte aligned",
+ caop->dst, ses->alignmask + 1);
+ if (!IS_ALIGNED((unsigned long)caop->auth_src, ses->alignmask + 1))
+ dwarning(2, "careful - source address %p is not %d byte aligned",
+ caop->auth_src, ses->alignmask + 1);
+ }
+
+ if (unlikely(kcaop->dst_len == 0 || caop->auth_len == 0)) {
+ dwarning(1, "Destination length cannot be zero");
+ return -EINVAL;
+ }
+
+ /* Note that in SRTP auth data overlap with data to be encrypted (dst)
+ */
+
+ auth_pagecount = PAGECOUNT(caop->auth_src, caop->auth_len);
+ diff = (int)(caop->src - caop->auth_src);
+ if (diff > MAX_SRTP_AUTH_DATA_DIFF || diff < 0) {
+ dwarning(1, "auth_src must overlap with src (diff: %d).", diff);
+ return -EINVAL;
+ }
+
+ pagecount = auth_pagecount;
+
+ rc = adjust_sg_array(ses, pagecount*2); /* double pages to have pages for dst(=auth_src) */
+ if (rc) {
+ derr(1, "cannot adjust sg array");
+ return rc;
+ }
+
+ rc = __get_userbuf(caop->auth_src, caop->auth_len, 1, auth_pagecount,
+ ses->pages, ses->sg, kcaop->task, kcaop->mm);
+ if (unlikely(rc)) {
+ derr(1, "failed to get user pages for data input");
+ return -EINVAL;
+ }
+
+ ses->used_pages = pagecount;
+ ses->readonly_pages = 0;
+
+ (*auth_sg) = ses->sg;
+
+ (*dst_sg) = ses->sg + auth_pagecount;
+ sg_init_table(*dst_sg, auth_pagecount);
+ sg_copy(ses->sg, (*dst_sg), caop->auth_len);
+ (*dst_sg) = sg_advance(*dst_sg, diff);
+ if (*dst_sg == NULL) {
+ release_user_pages(ses);
+ derr(1, "failed to get enough pages for auth data");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Return tag (digest) length for authenticated encryption
+ * If the cipher and digest are separate, hdata.init is set - just return
+ * digest length. Otherwise return digest length for aead ciphers
+ */
+static int cryptodev_get_tag_len(struct csession *ses_ptr)
+{
+ if (ses_ptr->hdata.init)
+ return ses_ptr->hdata.digestsize;
+ else
+ return cryptodev_cipher_get_tag_size(&ses_ptr->cdata);
+}
+
+/*
+ * Calculate destination buffer length for authenticated encryption. The
+ * expectation is that user-space code allocates exactly the same space for
+ * destination buffer before calling cryptodev. The result is cipher-dependent.
+ */
+static int cryptodev_get_dst_len(struct crypt_auth_op *caop, struct csession *ses_ptr)
+{
+ int dst_len = caop->len;
+ if (caop->op == COP_DECRYPT)
+ return dst_len;
+
+ dst_len += caop->tag_len;
+
+ /* for TLS always add some padding so the total length is rounded to
+ * cipher block size */
+ if (caop->flags & COP_FLAG_AEAD_TLS_TYPE) {
+ int bs = ses_ptr->cdata.blocksize;
+ dst_len += bs - (dst_len % bs);
+ }
+
+ return dst_len;
+}
+
+static int fill_kcaop_from_caop(struct kernel_crypt_auth_op *kcaop, struct fcrypt *fcr)
+{
+ struct crypt_auth_op *caop = &kcaop->caop;
+ struct csession *ses_ptr;
+ int ret;
+
+ /* this also enters ses_ptr->sem */
+ ses_ptr = crypto_get_session_by_sid(fcr, caop->ses);
+ if (unlikely(!ses_ptr)) {
+ derr(1, "invalid session ID=0x%08X", caop->ses);
+ return -EINVAL;
+ }
+
+ if (caop->flags & COP_FLAG_AEAD_TLS_TYPE || caop->flags & COP_FLAG_AEAD_SRTP_TYPE) {
+ if (caop->src != caop->dst) {
+ derr(1, "Non-inplace encryption and decryption is not efficient and not implemented");
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+ }
+
+ if (caop->tag_len == 0)
+ caop->tag_len = cryptodev_get_tag_len(ses_ptr);
+
+ kcaop->ivlen = caop->iv ? ses_ptr->cdata.ivsize : 0;
+ kcaop->dst_len = cryptodev_get_dst_len(caop, ses_ptr);
+ kcaop->task = current;
+ kcaop->mm = current->mm;
+
+ if (caop->iv) {
+ ret = copy_from_user(kcaop->iv, caop->iv, kcaop->ivlen);
+ if (unlikely(ret)) {
+ derr(1, "error copying IV (%d bytes), copy_from_user returned %d for address %p",
+ kcaop->ivlen, ret, caop->iv);
+ ret = -EFAULT;
+ goto out_unlock;
+ }
+ }
+
+ ret = 0;
+
+out_unlock:
+ crypto_put_session(ses_ptr);
+ return ret;
+
+}
+
+static int fill_caop_from_kcaop(struct kernel_crypt_auth_op *kcaop, struct fcrypt *fcr)
+{
+ int ret;
+
+ kcaop->caop.len = kcaop->dst_len;
+
+ if (kcaop->ivlen && kcaop->caop.flags & COP_FLAG_WRITE_IV) {
+ ret = copy_to_user(kcaop->caop.iv,
+ kcaop->iv, kcaop->ivlen);
+ if (unlikely(ret)) {
+ derr(1, "Error in copying to userspace");
+ return -EFAULT;
+ }
+ }
+ return 0;
+}
+
+
+int kcaop_from_user(struct kernel_crypt_auth_op *kcaop,
+ struct fcrypt *fcr, void __user *arg)
+{
+ if (unlikely(copy_from_user(&kcaop->caop, arg, sizeof(kcaop->caop)))) {
+ derr(1, "Error in copying from userspace");
+ return -EFAULT;
+ }
+
+ return fill_kcaop_from_caop(kcaop, fcr);
+}
+
+int kcaop_to_user(struct kernel_crypt_auth_op *kcaop,
+ struct fcrypt *fcr, void __user *arg)
+{
+ int ret;
+
+ ret = fill_caop_from_kcaop(kcaop, fcr);
+ if (unlikely(ret)) {
+ derr(1, "fill_caop_from_kcaop");
+ return ret;
+ }
+
+ if (unlikely(copy_to_user(arg, &kcaop->caop, sizeof(kcaop->caop)))) {
+ derr(1, "Error in copying to userspace");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static void copy_tls_hash(struct scatterlist *dst_sg, int len, void *hash, int hash_len)
+{
+ scatterwalk_map_and_copy(hash, dst_sg, len, hash_len, 1);
+}
+
+static void read_tls_hash(struct scatterlist *dst_sg, int len, void *hash, int hash_len)
+{
+ scatterwalk_map_and_copy(hash, dst_sg, len - hash_len, hash_len, 0);
+}
+
+#define TLS_MAX_PADDING_SIZE 256
+static int pad_record(struct scatterlist *dst_sg, int len, int block_size)
+{
+ uint8_t pad[TLS_MAX_PADDING_SIZE];
+ int pad_size = block_size - (len % block_size);
+
+ memset(pad, pad_size - 1, pad_size);
+
+ scatterwalk_map_and_copy(pad, dst_sg, len, pad_size, 1);
+
+ return pad_size;
+}
+
+static int verify_tls_record_pad(struct scatterlist *dst_sg, int len, int block_size)
+{
+ uint8_t pad[TLS_MAX_PADDING_SIZE];
+ uint8_t pad_size;
+ int i;
+
+ scatterwalk_map_and_copy(&pad_size, dst_sg, len - 1, 1, 0);
+
+ if (pad_size + 1 > len) {
+ derr(1, "Pad size: %d", pad_size);
+ return -EBADMSG;
+ }
+
+ scatterwalk_map_and_copy(pad, dst_sg, len - pad_size - 1, pad_size + 1, 0);
+
+ for (i = 0; i < pad_size; i++)
+ if (pad[i] != pad_size) {
+ derr(1, "Pad size: %u, pad: %d", pad_size, pad[i]);
+ return -EBADMSG;
+ }
+
+ return pad_size + 1;
+}
+
+/* Authenticate and encrypt the TLS way (also perform padding).
+ * During decryption it verifies the pad and tag and returns -EBADMSG on error.
+ */
+static int
+tls_auth_n_crypt(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop,
+ struct scatterlist *auth_sg, uint32_t auth_len,
+ struct scatterlist *dst_sg, uint32_t len)
+{
+ int ret, fail = 0;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ uint8_t vhash[AALG_MAX_RESULT_LEN];
+ uint8_t hash_output[AALG_MAX_RESULT_LEN];
+
+ /* TLS authenticates the plaintext except for the padding.
+ */
+ if (caop->op == COP_ENCRYPT) {
+ if (ses_ptr->hdata.init != 0) {
+ if (auth_len > 0) {
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ auth_sg, auth_len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_update: %d", ret);
+ return ret;
+ }
+ }
+
+ if (len > 0) {
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ dst_sg, len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_update: %d", ret);
+ return ret;
+ }
+ }
+
+ ret = cryptodev_hash_final(&ses_ptr->hdata, hash_output);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_final: %d", ret);
+ return ret;
+ }
+
+ copy_tls_hash(dst_sg, len, hash_output, caop->tag_len);
+ len += caop->tag_len;
+ }
+
+ if (ses_ptr->cdata.init != 0) {
+ if (ses_ptr->cdata.blocksize > 1) {
+ ret = pad_record(dst_sg, len, ses_ptr->cdata.blocksize);
+ len += ret;
+ }
+
+ ret = cryptodev_cipher_encrypt(&ses_ptr->cdata,
+ dst_sg, dst_sg, len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_cipher_encrypt: %d", ret);
+ return ret;
+ }
+ }
+ } else {
+ if (ses_ptr->cdata.init != 0) {
+ ret = cryptodev_cipher_decrypt(&ses_ptr->cdata,
+ dst_sg, dst_sg, len);
+
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_cipher_decrypt: %d", ret);
+ return ret;
+ }
+
+ if (ses_ptr->cdata.blocksize > 1) {
+ ret = verify_tls_record_pad(dst_sg, len, ses_ptr->cdata.blocksize);
+ if (unlikely(ret < 0)) {
+ derr(2, "verify_record_pad: %d", ret);
+ fail = 1;
+ } else {
+ len -= ret;
+ }
+ }
+ }
+
+ if (ses_ptr->hdata.init != 0) {
+ if (unlikely(caop->tag_len > sizeof(vhash) || caop->tag_len > len)) {
+ derr(1, "Illegal tag len size");
+ return -EINVAL;
+ }
+
+ read_tls_hash(dst_sg, len, vhash, caop->tag_len);
+ len -= caop->tag_len;
+
+ if (auth_len > 0) {
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ auth_sg, auth_len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_update: %d", ret);
+ return ret;
+ }
+ }
+
+ if (len > 0) {
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ dst_sg, len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_update: %d", ret);
+ return ret;
+ }
+ }
+
+ ret = cryptodev_hash_final(&ses_ptr->hdata, hash_output);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_final: %d", ret);
+ return ret;
+ }
+
+ if (memcmp(vhash, hash_output, caop->tag_len) != 0 || fail != 0) {
+ derr(2, "MAC verification failed (tag_len: %d)", caop->tag_len);
+ return -EBADMSG;
+ }
+ }
+ }
+ kcaop->dst_len = len;
+ return 0;
+}
+
+/* Authenticate and encrypt the SRTP way. During decryption
+ * it verifies the tag and returns -EBADMSG on error.
+ */
+static int
+srtp_auth_n_crypt(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop,
+ struct scatterlist *auth_sg, uint32_t auth_len,
+ struct scatterlist *dst_sg, uint32_t len)
+{
+ int ret, fail = 0;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ uint8_t vhash[AALG_MAX_RESULT_LEN];
+ uint8_t hash_output[AALG_MAX_RESULT_LEN];
+
+ /* SRTP authenticates the encrypted data.
+ */
+ if (caop->op == COP_ENCRYPT) {
+ if (ses_ptr->cdata.init != 0) {
+ ret = cryptodev_cipher_encrypt(&ses_ptr->cdata,
+ dst_sg, dst_sg, len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_cipher_encrypt: %d", ret);
+ return ret;
+ }
+ }
+
+ if (ses_ptr->hdata.init != 0) {
+ if (auth_len > 0) {
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ auth_sg, auth_len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_update: %d", ret);
+ return ret;
+ }
+ }
+
+ ret = cryptodev_hash_final(&ses_ptr->hdata, hash_output);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_final: %d", ret);
+ return ret;
+ }
+
+ if (unlikely(copy_to_user(caop->tag, hash_output, caop->tag_len)))
+ return -EFAULT;
+ }
+
+ } else {
+ if (ses_ptr->hdata.init != 0) {
+ if (unlikely(caop->tag_len > sizeof(vhash) || caop->tag_len > len)) {
+ derr(1, "Illegal tag len size");
+ return -EINVAL;
+ }
+
+ if (unlikely(copy_from_user(vhash, caop->tag, caop->tag_len)))
+ return -EFAULT;
+
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ auth_sg, auth_len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_update: %d", ret);
+ return ret;
+ }
+
+ ret = cryptodev_hash_final(&ses_ptr->hdata, hash_output);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_hash_final: %d", ret);
+ return ret;
+ }
+
+ if (memcmp(vhash, hash_output, caop->tag_len) != 0 || fail != 0) {
+ derr(2, "MAC verification failed");
+ return -EBADMSG;
+ }
+ }
+
+ if (ses_ptr->cdata.init != 0) {
+ ret = cryptodev_cipher_decrypt(&ses_ptr->cdata,
+ dst_sg, dst_sg, len);
+
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_cipher_decrypt: %d", ret);
+ return ret;
+ }
+ }
+
+ }
+ kcaop->dst_len = len;
+ return 0;
+}
+
+/* Typical AEAD (i.e. GCM) encryption/decryption.
+ * During decryption the tag is verified.
+ */
+static int
+auth_n_crypt(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop,
+ struct scatterlist *auth_sg, uint32_t auth_len,
+ struct scatterlist *src_sg,
+ struct scatterlist *dst_sg, uint32_t len)
+{
+ int ret;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ int max_tag_len;
+
+ max_tag_len = cryptodev_cipher_get_tag_size(&ses_ptr->cdata);
+ if (unlikely(caop->tag_len > max_tag_len)) {
+ derr(0, "Illegal tag length: %d", caop->tag_len);
+ return -EINVAL;
+ }
+
+ if (caop->tag_len)
+ cryptodev_cipher_set_tag_size(&ses_ptr->cdata, caop->tag_len);
+ else
+ caop->tag_len = max_tag_len;
+
+ cryptodev_cipher_auth(&ses_ptr->cdata, auth_sg, auth_len);
+
+ if (caop->op == COP_ENCRYPT) {
+ ret = cryptodev_cipher_encrypt(&ses_ptr->cdata,
+ src_sg, dst_sg, len);
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_cipher_encrypt: %d", ret);
+ return ret;
+ }
+ kcaop->dst_len = len + caop->tag_len;
+ caop->tag = caop->dst + len;
+ } else {
+ ret = cryptodev_cipher_decrypt(&ses_ptr->cdata,
+ src_sg, dst_sg, len);
+
+ if (unlikely(ret)) {
+ derr(0, "cryptodev_cipher_decrypt: %d", ret);
+ return ret;
+ }
+ kcaop->dst_len = len - caop->tag_len;
+ caop->tag = caop->dst + len - caop->tag_len;
+ }
+
+ return 0;
+}
+
+static int crypto_auth_zc_srtp(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
+{
+ struct scatterlist *dst_sg, *auth_sg;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ int ret;
+
+ if (unlikely(ses_ptr->cdata.init != 0 &&
+ (ses_ptr->cdata.stream == 0 || ses_ptr->cdata.aead != 0))) {
+ derr(0, "Only stream modes are allowed in SRTP mode (but not AEAD)");
+ return -EINVAL;
+ }
+
+ ret = get_userbuf_srtp(ses_ptr, kcaop, &auth_sg, &dst_sg);
+ if (unlikely(ret)) {
+ derr(1, "get_userbuf_srtp(): Error getting user pages.");
+ return ret;
+ }
+
+ ret = srtp_auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
+ dst_sg, caop->len);
+
+ release_user_pages(ses_ptr);
+
+ return ret;
+}
+
+static int crypto_auth_zc_tls(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
+{
+ struct crypt_auth_op *caop = &kcaop->caop;
+ struct scatterlist *dst_sg, *auth_sg;
+ unsigned char *auth_buf = NULL;
+ struct scatterlist tmp;
+ int ret;
+
+ if (unlikely(caop->auth_len > PAGE_SIZE)) {
+ derr(1, "auth data len is excessive.");
+ return -EINVAL;
+ }
+
+ auth_buf = (char *)__get_free_page(GFP_KERNEL);
+ if (unlikely(!auth_buf)) {
+ derr(1, "unable to get a free page.");
+ return -ENOMEM;
+ }
+
+ if (caop->auth_src && caop->auth_len > 0) {
+ if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
+ derr(1, "unable to copy auth data from userspace.");
+ ret = -EFAULT;
+ goto free_auth_buf;
+ }
+
+ sg_init_one(&tmp, auth_buf, caop->auth_len);
+ auth_sg = &tmp;
+ } else {
+ auth_sg = NULL;
+ }
+
+ ret = get_userbuf_tls(ses_ptr, kcaop, &dst_sg);
+ if (unlikely(ret)) {
+ derr(1, "get_userbuf_tls(): Error getting user pages.");
+ goto free_auth_buf;
+ }
+
+ ret = tls_auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
+ dst_sg, caop->len);
+ release_user_pages(ses_ptr);
+
+free_auth_buf:
+ free_page((unsigned long)auth_buf);
+ return ret;
+}
+
+static int crypto_auth_zc_aead(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
+{
+ struct scatterlist *dst_sg;
+ struct scatterlist *src_sg;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ unsigned char *auth_buf = NULL;
+ int ret;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
+ struct scatterlist tmp;
+ struct scatterlist *auth_sg;
+#else
+ struct scatterlist auth1[2];
+ struct scatterlist auth2[2];
+#endif
+
+ if (unlikely(ses_ptr->cdata.init == 0 ||
+ (ses_ptr->cdata.stream == 0 && ses_ptr->cdata.aead == 0))) {
+ derr(0, "Only stream and AEAD ciphers are allowed for authenc");
+ return -EINVAL;
+ }
+
+ if (unlikely(caop->auth_len > PAGE_SIZE)) {
+ derr(1, "auth data len is excessive.");
+ return -EINVAL;
+ }
+
+ auth_buf = (char *)__get_free_page(GFP_KERNEL);
+ if (unlikely(!auth_buf)) {
+ derr(1, "unable to get a free page.");
+ return -ENOMEM;
+ }
+
+ ret = get_userbuf(ses_ptr, caop->src, caop->len, caop->dst, kcaop->dst_len,
+ kcaop->task, kcaop->mm, &src_sg, &dst_sg);
+ if (unlikely(ret)) {
+ derr(1, "get_userbuf(): Error getting user pages.");
+ goto free_auth_buf;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
+ if (caop->auth_src && caop->auth_len > 0) {
+ if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
+ derr(1, "unable to copy auth data from userspace.");
+ ret = -EFAULT;
+ goto free_pages;
+ }
+
+ sg_init_one(&tmp, auth_buf, caop->auth_len);
+ auth_sg = &tmp;
+ } else {
+ auth_sg = NULL;
+ }
+
+ ret = auth_n_crypt(ses_ptr, kcaop, auth_sg, caop->auth_len,
+ src_sg, dst_sg, caop->len);
+#else
+ if (caop->auth_src && caop->auth_len > 0) {
+ if (unlikely(copy_from_user(auth_buf, caop->auth_src, caop->auth_len))) {
+ derr(1, "unable to copy auth data from userspace.");
+ ret = -EFAULT;
+ goto free_pages;
+ }
+
+ sg_init_table(auth1, 2);
+ sg_set_buf(auth1, auth_buf, caop->auth_len);
+ sg_chain(auth1, 2, src_sg);
+
+ if (src_sg == dst_sg) {
+ src_sg = auth1;
+ dst_sg = auth1;
+ } else {
+ sg_init_table(auth2, 2);
+ sg_set_buf(auth2, auth_buf, caop->auth_len);
+ sg_chain(auth2, 2, dst_sg);
+ src_sg = auth1;
+ dst_sg = auth2;
+ }
+ }
+
+ ret = auth_n_crypt(ses_ptr, kcaop, NULL, caop->auth_len,
+ src_sg, dst_sg, caop->len);
+#endif
+
+free_pages:
+ release_user_pages(ses_ptr);
+
+free_auth_buf:
+ free_page((unsigned long)auth_buf);
+
+ return ret;
+}
+
+static int
+__crypto_auth_run_zc(struct csession *ses_ptr, struct kernel_crypt_auth_op *kcaop)
+{
+ struct crypt_auth_op *caop = &kcaop->caop;
+ int ret;
+
+ if (caop->flags & COP_FLAG_AEAD_SRTP_TYPE) {
+ ret = crypto_auth_zc_srtp(ses_ptr, kcaop);
+ } else if (caop->flags & COP_FLAG_AEAD_TLS_TYPE &&
+ ses_ptr->cdata.aead == 0) {
+ ret = crypto_auth_zc_tls(ses_ptr, kcaop);
+ } else if (ses_ptr->cdata.aead) {
+ ret = crypto_auth_zc_aead(ses_ptr, kcaop);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+
+int crypto_auth_run(struct fcrypt *fcr, struct kernel_crypt_auth_op *kcaop)
+{
+ struct csession *ses_ptr;
+ struct crypt_auth_op *caop = &kcaop->caop;
+ int ret;
+
+ if (unlikely(caop->op != COP_ENCRYPT && caop->op != COP_DECRYPT)) {
+ ddebug(1, "invalid operation op=%u", caop->op);
+ return -EINVAL;
+ }
+
+ /* this also enters ses_ptr->sem */
+ ses_ptr = crypto_get_session_by_sid(fcr, caop->ses);
+ if (unlikely(!ses_ptr)) {
+ derr(1, "invalid session ID=0x%08X", caop->ses);
+ return -EINVAL;
+ }
+
+ if (unlikely(ses_ptr->cdata.init == 0)) {
+ derr(1, "cipher context not initialized");
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ /* If we have a hash/mac handle reset its state */
+ if (ses_ptr->hdata.init != 0) {
+ ret = cryptodev_hash_reset(&ses_ptr->hdata);
+ if (unlikely(ret)) {
+ derr(1, "error in cryptodev_hash_reset()");
+ goto out_unlock;
+ }
+ }
+
+ cryptodev_cipher_set_iv(&ses_ptr->cdata, kcaop->iv,
+ min(ses_ptr->cdata.ivsize, kcaop->ivlen));
+
+ ret = __crypto_auth_run_zc(ses_ptr, kcaop);
+ if (unlikely(ret)) {
+ derr(1, "error in __crypto_auth_run_zc()");
+ goto out_unlock;
+ }
+
+ ret = 0;
+
+ cryptodev_cipher_get_iv(&ses_ptr->cdata, kcaop->iv,
+ min(ses_ptr->cdata.ivsize, kcaop->ivlen));
+
+out_unlock:
+ crypto_put_session(ses_ptr);
+ return ret;
+}
diff --git a/drivers/cryptodev-linux-master/cipherapi.h b/drivers/cryptodev-linux-master/cipherapi.h
new file mode 100644
index 00000000..b6ed6c27
--- /dev/null
+++ b/drivers/cryptodev-linux-master/cipherapi.h
@@ -0,0 +1,56 @@
+#ifndef CIPHERAPI_H
+# define CIPHERAPI_H
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
+# include <linux/crypto.h>
+
+typedef struct crypto_ablkcipher cryptodev_crypto_blkcipher_t;
+typedef struct ablkcipher_request cryptodev_blkcipher_request_t;
+
+# define cryptodev_crypto_alloc_blkcipher crypto_alloc_ablkcipher
+# define cryptodev_crypto_blkcipher_blocksize crypto_ablkcipher_blocksize
+# define cryptodev_crypto_blkcipher_ivsize crypto_ablkcipher_ivsize
+# define cryptodev_crypto_blkcipher_alignmask crypto_ablkcipher_alignmask
+# define cryptodev_crypto_blkcipher_setkey crypto_ablkcipher_setkey
+
+static inline void cryptodev_crypto_free_blkcipher(cryptodev_crypto_blkcipher_t *c) {
+ if (c)
+ crypto_free_ablkcipher(c);
+}
+
+# define cryptodev_blkcipher_request_alloc ablkcipher_request_alloc
+# define cryptodev_blkcipher_request_set_callback ablkcipher_request_set_callback
+
+static inline void cryptodev_blkcipher_request_free(cryptodev_blkcipher_request_t *r) {
+ if (r)
+ ablkcipher_request_free(r);
+}
+
+# define cryptodev_blkcipher_request_set_crypt ablkcipher_request_set_crypt
+# define cryptodev_crypto_blkcipher_encrypt crypto_ablkcipher_encrypt
+# define cryptodev_crypto_blkcipher_decrypt crypto_ablkcipher_decrypt
+# define cryptodev_crypto_blkcipher_tfm crypto_ablkcipher_tfm
+#else
+#include <crypto/skcipher.h>
+
+typedef struct crypto_skcipher cryptodev_crypto_blkcipher_t;
+typedef struct skcipher_request cryptodev_blkcipher_request_t;
+
+# define cryptodev_crypto_alloc_blkcipher crypto_alloc_skcipher
+# define cryptodev_crypto_blkcipher_blocksize crypto_skcipher_blocksize
+# define cryptodev_crypto_blkcipher_ivsize crypto_skcipher_ivsize
+# define cryptodev_crypto_blkcipher_alignmask crypto_skcipher_alignmask
+# define cryptodev_crypto_blkcipher_setkey crypto_skcipher_setkey
+# define cryptodev_crypto_free_blkcipher crypto_free_skcipher
+# define cryptodev_blkcipher_request_alloc skcipher_request_alloc
+# define cryptodev_blkcipher_request_set_callback skcipher_request_set_callback
+# define cryptodev_blkcipher_request_free skcipher_request_free
+# define cryptodev_blkcipher_request_set_crypt skcipher_request_set_crypt
+# define cryptodev_crypto_blkcipher_encrypt crypto_skcipher_encrypt
+# define cryptodev_crypto_blkcipher_decrypt crypto_skcipher_decrypt
+# define cryptodev_crypto_blkcipher_tfm crypto_skcipher_tfm
+#endif
+
+#endif
diff --git a/drivers/cryptodev-linux-master/cryptlib.c b/drivers/cryptodev-linux-master/cryptlib.c
new file mode 100644
index 00000000..e2a4198a
--- /dev/null
+++ b/drivers/cryptodev-linux-master/cryptlib.c
@@ -0,0 +1,492 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2010,2011 Nikos Mavrogiannopoulos <nmav@gnutls.org>
+ * Portions Copyright (c) 2010 Michael Weiser
+ * Portions Copyright (c) 2010 Phil Sutter
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/ioctl.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <linux/uaccess.h>
+#include <crypto/algapi.h>
+#include <crypto/hash.h>
+#include <crypto/cryptodev.h>
+#include <crypto/aead.h>
+#include <linux/rtnetlink.h>
+#include <crypto/authenc.h>
+#include "cryptodev_int.h"
+#include "cipherapi.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
+extern const struct crypto_type crypto_givcipher_type;
+#endif
+
+static void cryptodev_complete(struct crypto_async_request *req, int err)
+{
+ struct cryptodev_result *res = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ res->err = err;
+ complete(&res->completion);
+}
+
+int cryptodev_get_cipher_keylen(unsigned int *keylen, struct session_op *sop,
+ int aead)
+{
+ /*
+ * For blockciphers (AES-CBC) or non-composite aead ciphers (like AES-GCM),
+ * the key length is simply the cipher keylen obtained from userspace. If
+ * the cipher is composite aead, the keylen is the sum of cipher keylen,
+ * hmac keylen and a key header length. This key format is the one used in
+ * Linux kernel for composite aead ciphers (crypto/authenc.c)
+ */
+ unsigned int klen = sop->keylen;
+
+ if (unlikely(sop->keylen > CRYPTO_CIPHER_MAX_KEY_LEN))
+ return -EINVAL;
+
+ if (aead && sop->mackeylen) {
+ if (unlikely(sop->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN))
+ return -EINVAL;
+ klen += sop->mackeylen;
+ klen += RTA_SPACE(sizeof(struct crypto_authenc_key_param));
+ }
+
+ *keylen = klen;
+ return 0;
+}
+
+int cryptodev_get_cipher_key(uint8_t *key, struct session_op *sop, int aead)
+{
+ /*
+ * Get cipher key from user-space. For blockciphers just copy it from
+ * user-space. For composite aead ciphers combine it with the hmac key in
+ * the format used by Linux kernel in crypto/authenc.c:
+ *
+ * [[AUTHENC_KEY_HEADER + CIPHER_KEYLEN] [AUTHENTICATION KEY] [CIPHER KEY]]
+ */
+ struct crypto_authenc_key_param *param;
+ struct rtattr *rta;
+ int ret = 0;
+
+ if (aead && sop->mackeylen) {
+ /*
+ * Composite aead ciphers. The first four bytes are the header type and
+ * header length for aead keys
+ */
+ rta = (void *)key;
+ rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
+ rta->rta_len = RTA_LENGTH(sizeof(*param));
+
+ /*
+ * The next four bytes hold the length of the encryption key
+ */
+ param = RTA_DATA(rta);
+ param->enckeylen = cpu_to_be32(sop->keylen);
+
+ /* Advance key pointer eight bytes and copy the hmac key */
+ key += RTA_SPACE(sizeof(*param));
+ if (unlikely(copy_from_user(key, sop->mackey, sop->mackeylen))) {
+ ret = -EFAULT;
+ goto error;
+ }
+ /* Advance key pointer past the hmac key */
+ key += sop->mackeylen;
+ }
+ /* now copy the blockcipher key */
+ if (unlikely(copy_from_user(key, sop->key, sop->keylen)))
+ ret = -EFAULT;
+
+error:
+ return ret;
+}
+
+/* Was correct key length supplied? */
+static int check_key_size(size_t keylen, const char *alg_name,
+ unsigned int min_keysize, unsigned int max_keysize)
+{
+ if (max_keysize > 0 && unlikely((keylen < min_keysize) ||
+ (keylen > max_keysize))) {
+ ddebug(1, "Wrong keylen '%zu' for algorithm '%s'. Use %u to %u.",
+ keylen, alg_name, min_keysize, max_keysize);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int cryptodev_cipher_init(struct cipher_data *out, const char *alg_name,
+ uint8_t *keyp, size_t keylen, int stream, int aead)
+{
+ int ret;
+
+ if (aead == 0) {
+ unsigned int min_keysize, max_keysize;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
+ struct crypto_tfm *tfm;
+#else
+ struct ablkcipher_alg *alg;
+#endif
+
+ out->async.s = cryptodev_crypto_alloc_blkcipher(alg_name, 0, 0);
+ if (unlikely(IS_ERR(out->async.s))) {
+ ddebug(1, "Failed to load cipher %s", alg_name);
+ return -EINVAL;
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
+ tfm = crypto_skcipher_tfm(out->async.s);
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(5, 4, 0))
+ if ((tfm->__crt_alg->cra_type == &crypto_ablkcipher_type)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
+ || (tfm->__crt_alg->cra_type == &crypto_givcipher_type)
+#endif
+ ) {
+ struct ablkcipher_alg *alg;
+
+ alg = &tfm->__crt_alg->cra_ablkcipher;
+ min_keysize = alg->min_keysize;
+ max_keysize = alg->max_keysize;
+ } else
+#endif
+ {
+ struct skcipher_alg *alg;
+
+ alg = crypto_skcipher_alg(out->async.s);
+ min_keysize = alg->min_keysize;
+ max_keysize = alg->max_keysize;
+ }
+#else
+ alg = crypto_ablkcipher_alg(out->async.s);
+ min_keysize = alg->min_keysize;
+ max_keysize = alg->max_keysize;
+#endif
+ ret = check_key_size(keylen, alg_name, min_keysize,
+ max_keysize);
+ if (ret)
+ goto error;
+
+ out->blocksize = cryptodev_crypto_blkcipher_blocksize(out->async.s);
+ out->ivsize = cryptodev_crypto_blkcipher_ivsize(out->async.s);
+ out->alignmask = cryptodev_crypto_blkcipher_alignmask(out->async.s);
+
+ ret = cryptodev_crypto_blkcipher_setkey(out->async.s, keyp, keylen);
+ } else {
+ out->async.as = crypto_alloc_aead(alg_name, 0, 0);
+ if (unlikely(IS_ERR(out->async.as))) {
+ ddebug(1, "Failed to load cipher %s", alg_name);
+ return -EINVAL;
+ }
+
+ out->blocksize = crypto_aead_blocksize(out->async.as);
+ out->ivsize = crypto_aead_ivsize(out->async.as);
+ out->alignmask = crypto_aead_alignmask(out->async.as);
+
+ ret = crypto_aead_setkey(out->async.as, keyp, keylen);
+ }
+
+ if (unlikely(ret)) {
+ ddebug(1, "Setting key failed for %s-%zu.", alg_name, keylen*8);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ out->stream = stream;
+ out->aead = aead;
+
+ init_completion(&out->async.result.completion);
+
+ if (aead == 0) {
+ out->async.request = cryptodev_blkcipher_request_alloc(out->async.s, GFP_KERNEL);
+ if (unlikely(!out->async.request)) {
+ derr(1, "error allocating async crypto request");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ cryptodev_blkcipher_request_set_callback(out->async.request,
+ CRYPTO_TFM_REQ_MAY_BACKLOG,
+ cryptodev_complete, &out->async.result);
+ } else {
+ out->async.arequest = aead_request_alloc(out->async.as, GFP_KERNEL);
+ if (unlikely(!out->async.arequest)) {
+ derr(1, "error allocating async crypto request");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ aead_request_set_callback(out->async.arequest,
+ CRYPTO_TFM_REQ_MAY_BACKLOG,
+ cryptodev_complete, &out->async.result);
+ }
+
+ out->init = 1;
+ return 0;
+error:
+ if (aead == 0) {
+ cryptodev_blkcipher_request_free(out->async.request);
+ cryptodev_crypto_free_blkcipher(out->async.s);
+ } else {
+ if (out->async.arequest)
+ aead_request_free(out->async.arequest);
+ if (out->async.as)
+ crypto_free_aead(out->async.as);
+ }
+
+ return ret;
+}
+
+void cryptodev_cipher_deinit(struct cipher_data *cdata)
+{
+ if (cdata->init) {
+ if (cdata->aead == 0) {
+ cryptodev_blkcipher_request_free(cdata->async.request);
+ cryptodev_crypto_free_blkcipher(cdata->async.s);
+ } else {
+ if (cdata->async.arequest)
+ aead_request_free(cdata->async.arequest);
+ if (cdata->async.as)
+ crypto_free_aead(cdata->async.as);
+ }
+
+ cdata->init = 0;
+ }
+}
+
+static inline int waitfor(struct cryptodev_result *cr, ssize_t ret)
+{
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ wait_for_completion(&cr->completion);
+ /* At this point we known for sure the request has finished,
+ * because wait_for_completion above was not interruptible.
+ * This is important because otherwise hardware or driver
+ * might try to access memory which will be freed or reused for
+ * another request. */
+
+ if (unlikely(cr->err)) {
+ derr(0, "error from async request: %d", cr->err);
+ return cr->err;
+ }
+
+ break;
+ default:
+ return ret;
+ }
+
+ return 0;
+}
+
+ssize_t cryptodev_cipher_encrypt(struct cipher_data *cdata,
+ const struct scatterlist *src, struct scatterlist *dst,
+ size_t len)
+{
+ int ret;
+
+ reinit_completion(&cdata->async.result.completion);
+
+ if (cdata->aead == 0) {
+ cryptodev_blkcipher_request_set_crypt(cdata->async.request,
+ (struct scatterlist *)src, dst,
+ len, cdata->async.iv);
+ ret = cryptodev_crypto_blkcipher_encrypt(cdata->async.request);
+ } else {
+ aead_request_set_crypt(cdata->async.arequest,
+ (struct scatterlist *)src, dst,
+ len, cdata->async.iv);
+ ret = crypto_aead_encrypt(cdata->async.arequest);
+ }
+
+ return waitfor(&cdata->async.result, ret);
+}
+
+ssize_t cryptodev_cipher_decrypt(struct cipher_data *cdata,
+ const struct scatterlist *src, struct scatterlist *dst,
+ size_t len)
+{
+ int ret;
+
+ reinit_completion(&cdata->async.result.completion);
+ if (cdata->aead == 0) {
+ cryptodev_blkcipher_request_set_crypt(cdata->async.request,
+ (struct scatterlist *)src, dst,
+ len, cdata->async.iv);
+ ret = cryptodev_crypto_blkcipher_decrypt(cdata->async.request);
+ } else {
+ aead_request_set_crypt(cdata->async.arequest,
+ (struct scatterlist *)src, dst,
+ len, cdata->async.iv);
+ ret = crypto_aead_decrypt(cdata->async.arequest);
+ }
+
+ return waitfor(&cdata->async.result, ret);
+}
+
+/* Hash functions */
+
+int cryptodev_hash_init(struct hash_data *hdata, const char *alg_name,
+ int hmac_mode, void *mackey, size_t mackeylen)
+{
+ int ret;
+
+ hdata->async.s = crypto_alloc_ahash(alg_name, 0, 0);
+ if (unlikely(IS_ERR(hdata->async.s))) {
+ ddebug(1, "Failed to load transform for %s", alg_name);
+ return -EINVAL;
+ }
+
+ /* Copy the key from user and set to TFM. */
+ if (hmac_mode != 0) {
+ ret = crypto_ahash_setkey(hdata->async.s, mackey, mackeylen);
+ if (unlikely(ret)) {
+ ddebug(1, "Setting hmac key failed for %s-%zu.",
+ alg_name, mackeylen*8);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ hdata->digestsize = crypto_ahash_digestsize(hdata->async.s);
+ hdata->alignmask = crypto_ahash_alignmask(hdata->async.s);
+
+ init_completion(&hdata->async.result.completion);
+
+ hdata->async.request = ahash_request_alloc(hdata->async.s, GFP_KERNEL);
+ if (unlikely(!hdata->async.request)) {
+ derr(0, "error allocating async crypto request");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ ahash_request_set_callback(hdata->async.request,
+ CRYPTO_TFM_REQ_MAY_BACKLOG,
+ cryptodev_complete, &hdata->async.result);
+ hdata->init = 1;
+ return 0;
+
+error:
+ crypto_free_ahash(hdata->async.s);
+ return ret;
+}
+
+void cryptodev_hash_deinit(struct hash_data *hdata)
+{
+ if (hdata->init) {
+ ahash_request_free(hdata->async.request);
+ crypto_free_ahash(hdata->async.s);
+ hdata->init = 0;
+ }
+}
+
+int cryptodev_hash_reset(struct hash_data *hdata)
+{
+ int ret;
+
+ ret = crypto_ahash_init(hdata->async.request);
+ if (unlikely(ret)) {
+ derr(0, "error in crypto_hash_init()");
+ return ret;
+ }
+
+ return 0;
+
+}
+
+ssize_t cryptodev_hash_update(struct hash_data *hdata,
+ struct scatterlist *sg, size_t len)
+{
+ int ret;
+
+ reinit_completion(&hdata->async.result.completion);
+ ahash_request_set_crypt(hdata->async.request, sg, NULL, len);
+
+ ret = crypto_ahash_update(hdata->async.request);
+
+ return waitfor(&hdata->async.result, ret);
+}
+
+int cryptodev_hash_final(struct hash_data *hdata, void *output)
+{
+ int ret;
+
+ reinit_completion(&hdata->async.result.completion);
+ ahash_request_set_crypt(hdata->async.request, NULL, output, 0);
+
+ ret = crypto_ahash_final(hdata->async.request);
+
+ return waitfor(&hdata->async.result, ret);
+}
+
+#ifdef CIOCCPHASH
+/* import the current hash state of src to dst */
+int cryptodev_hash_copy(struct hash_data *dst, struct hash_data *src)
+{
+ int ret, statesize;
+ void *statedata = NULL;
+ struct crypto_tfm *tfm;
+
+ if (unlikely(src == NULL || dst == NULL)) {
+ return -EINVAL;
+ }
+
+ reinit_completion(&src->async.result.completion);
+
+ statesize = crypto_ahash_statesize(src->async.s);
+ if (unlikely(statesize <= 0)) {
+ return -EINVAL;
+ }
+
+ statedata = kzalloc(statesize, GFP_KERNEL);
+ if (unlikely(statedata == NULL)) {
+ return -ENOMEM;
+ }
+
+ ret = crypto_ahash_export(src->async.request, statedata);
+ if (unlikely(ret < 0)) {
+ if (unlikely(ret == -ENOSYS)) {
+ tfm = crypto_ahash_tfm(src->async.s);
+ derr(0, "cryptodev_hash_copy: crypto_ahash_export not implemented for "
+ "alg='%s', driver='%s'", crypto_tfm_alg_name(tfm),
+ crypto_tfm_alg_driver_name(tfm));
+ }
+ goto out;
+ }
+
+ ret = crypto_ahash_import(dst->async.request, statedata);
+ if (unlikely(ret == -ENOSYS)) {
+ tfm = crypto_ahash_tfm(dst->async.s);
+ derr(0, "cryptodev_hash_copy: crypto_ahash_import not implemented for "
+ "alg='%s', driver='%s'", crypto_tfm_alg_name(tfm),
+ crypto_tfm_alg_driver_name(tfm));
+ }
+out:
+ kfree(statedata);
+ return ret;
+}
+#endif /* CIOCCPHASH */
diff --git a/drivers/cryptodev-linux-master/cryptlib.h b/drivers/cryptodev-linux-master/cryptlib.h
new file mode 100644
index 00000000..9330ff57
--- /dev/null
+++ b/drivers/cryptodev-linux-master/cryptlib.h
@@ -0,0 +1,109 @@
+#ifndef CRYPTLIB_H
+# define CRYPTLIB_H
+
+#include <linux/version.h>
+
+struct cryptodev_result {
+ struct completion completion;
+ int err;
+};
+
+#include "cipherapi.h"
+
+struct cipher_data {
+ int init; /* 0 uninitialized */
+ int blocksize;
+ int aead;
+ int stream;
+ int ivsize;
+ int alignmask;
+ struct {
+ /* block ciphers */
+ cryptodev_crypto_blkcipher_t *s;
+ cryptodev_blkcipher_request_t *request;
+
+ /* AEAD ciphers */
+ struct crypto_aead *as;
+ struct aead_request *arequest;
+
+ struct cryptodev_result result;
+ uint8_t iv[EALG_MAX_BLOCK_LEN];
+ } async;
+};
+
+int cryptodev_cipher_init(struct cipher_data *out, const char *alg_name,
+ uint8_t *key, size_t keylen, int stream, int aead);
+void cryptodev_cipher_deinit(struct cipher_data *cdata);
+int cryptodev_get_cipher_key(uint8_t *key, struct session_op *sop, int aead);
+int cryptodev_get_cipher_keylen(unsigned int *keylen, struct session_op *sop,
+ int aead);
+ssize_t cryptodev_cipher_decrypt(struct cipher_data *cdata,
+ const struct scatterlist *sg1,
+ struct scatterlist *sg2, size_t len);
+ssize_t cryptodev_cipher_encrypt(struct cipher_data *cdata,
+ const struct scatterlist *sg1,
+ struct scatterlist *sg2, size_t len);
+
+/* AEAD */
+static inline void cryptodev_cipher_auth(struct cipher_data *cdata,
+ struct scatterlist *sg1, size_t len)
+{
+ /* for some reason we _have_ to call that even for zero length sgs */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0))
+ aead_request_set_assoc(cdata->async.arequest, len ? sg1 : NULL, len);
+#else
+ aead_request_set_ad(cdata->async.arequest, len);
+#endif
+}
+
+static inline void cryptodev_cipher_set_tag_size(struct cipher_data *cdata, int size)
+{
+ if (likely(cdata->aead != 0))
+ crypto_aead_setauthsize(cdata->async.as, size);
+}
+
+static inline int cryptodev_cipher_get_tag_size(struct cipher_data *cdata)
+{
+ if (likely(cdata->init && cdata->aead != 0))
+ return crypto_aead_authsize(cdata->async.as);
+ else
+ return 0;
+}
+
+static inline void cryptodev_cipher_set_iv(struct cipher_data *cdata,
+ void *iv, size_t iv_size)
+{
+ memcpy(cdata->async.iv, iv, min(iv_size, sizeof(cdata->async.iv)));
+}
+
+static inline void cryptodev_cipher_get_iv(struct cipher_data *cdata,
+ void *iv, size_t iv_size)
+{
+ memcpy(iv, cdata->async.iv, min(iv_size, sizeof(cdata->async.iv)));
+}
+
+/* Hash */
+struct hash_data {
+ int init; /* 0 uninitialized */
+ int digestsize;
+ int alignmask;
+ struct {
+ struct crypto_ahash *s;
+ struct cryptodev_result result;
+ struct ahash_request *request;
+ } async;
+};
+
+int cryptodev_hash_final(struct hash_data *hdata, void *output);
+ssize_t cryptodev_hash_update(struct hash_data *hdata,
+ struct scatterlist *sg, size_t len);
+int cryptodev_hash_reset(struct hash_data *hdata);
+void cryptodev_hash_deinit(struct hash_data *hdata);
+int cryptodev_hash_init(struct hash_data *hdata, const char *alg_name,
+ int hmac_mode, void *mackey, size_t mackeylen);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+int cryptodev_hash_copy(struct hash_data *dst, struct hash_data *src);
+#endif
+
+
+#endif
diff --git a/drivers/cryptodev-linux-master/crypto/cryptodev.h b/drivers/cryptodev-linux-master/crypto/cryptodev.h
new file mode 100644
index 00000000..1def37a0
--- /dev/null
+++ b/drivers/cryptodev-linux-master/crypto/cryptodev.h
@@ -0,0 +1,319 @@
+/* This is a source compatible implementation with the original API of
+ * cryptodev by Angelos D. Keromytis, found at openbsd cryptodev.h.
+ * Placed under public domain */
+
+#ifndef L_CRYPTODEV_H
+#define L_CRYPTODEV_H
+
+#include <linux/types.h>
+#include <linux/version.h>
+#ifndef __KERNEL__
+#define __user
+#endif
+
+/* API extensions for linux */
+#define CRYPTO_HMAC_MAX_KEY_LEN 512
+#define CRYPTO_CIPHER_MAX_KEY_LEN 64
+
+/* All the supported algorithms
+ */
+enum cryptodev_crypto_op_t {
+ CRYPTO_DES_CBC = 1,
+ CRYPTO_3DES_CBC = 2,
+ CRYPTO_BLF_CBC = 3,
+ CRYPTO_CAST_CBC = 4,
+ CRYPTO_SKIPJACK_CBC = 5,
+ CRYPTO_MD5_HMAC = 6,
+ CRYPTO_SHA1_HMAC = 7,
+ CRYPTO_RIPEMD160_HMAC = 8,
+ CRYPTO_MD5_KPDK = 9,
+ CRYPTO_SHA1_KPDK = 10,
+ CRYPTO_RIJNDAEL128_CBC = 11,
+ CRYPTO_AES_CBC = CRYPTO_RIJNDAEL128_CBC,
+ CRYPTO_ARC4 = 12,
+ CRYPTO_MD5 = 13,
+ CRYPTO_SHA1 = 14,
+ CRYPTO_DEFLATE_COMP = 15,
+ CRYPTO_NULL = 16,
+ CRYPTO_LZS_COMP = 17,
+ CRYPTO_SHA2_256_HMAC = 18,
+ CRYPTO_SHA2_384_HMAC = 19,
+ CRYPTO_SHA2_512_HMAC = 20,
+ CRYPTO_AES_CTR = 21,
+ CRYPTO_AES_XTS = 22,
+ CRYPTO_AES_ECB = 23,
+ CRYPTO_AES_GCM = 50,
+
+ CRYPTO_CAMELLIA_CBC = 101,
+ CRYPTO_RIPEMD160,
+ CRYPTO_SHA2_224,
+ CRYPTO_SHA2_256,
+ CRYPTO_SHA2_384,
+ CRYPTO_SHA2_512,
+ CRYPTO_SHA2_224_HMAC,
+ CRYPTO_TLS11_AES_CBC_HMAC_SHA1,
+ CRYPTO_TLS12_AES_CBC_HMAC_SHA256,
+ CRYPTO_ALGORITHM_ALL, /* Keep updated - see below */
+};
+
+#define CRYPTO_ALGORITHM_MAX (CRYPTO_ALGORITHM_ALL - 1)
+
+/* Values for ciphers */
+#define DES_BLOCK_LEN 8
+#define DES3_BLOCK_LEN 8
+#define RIJNDAEL128_BLOCK_LEN 16
+#define AES_BLOCK_LEN RIJNDAEL128_BLOCK_LEN
+#define CAMELLIA_BLOCK_LEN 16
+#define BLOWFISH_BLOCK_LEN 8
+#define SKIPJACK_BLOCK_LEN 8
+#define CAST128_BLOCK_LEN 8
+
+/* the maximum of the above */
+#define EALG_MAX_BLOCK_LEN 16
+
+/* Values for hashes/MAC */
+#define AALG_MAX_RESULT_LEN 64
+
+/* maximum length of verbose alg names (depends on CRYPTO_MAX_ALG_NAME) */
+#define CRYPTODEV_MAX_ALG_NAME 64
+
+#define HASH_MAX_LEN 64
+
+/* input of CIOCGSESSION */
+struct session_op {
+ /* Specify either cipher or mac
+ */
+ __u32 cipher; /* cryptodev_crypto_op_t */
+ __u32 mac; /* cryptodev_crypto_op_t */
+
+ __u32 keylen;
+ __u8 __user *key;
+ __u32 mackeylen;
+ __u8 __user *mackey;
+
+ __u32 ses; /* session identifier */
+};
+
+struct session_info_op {
+ __u32 ses; /* session identifier */
+
+ /* verbose names for the requested ciphers */
+ struct alg_info {
+ char cra_name[CRYPTODEV_MAX_ALG_NAME];
+ char cra_driver_name[CRYPTODEV_MAX_ALG_NAME];
+ } cipher_info, hash_info;
+
+ __u16 alignmask; /* alignment constraints */
+ __u32 flags; /* SIOP_FLAGS_* */
+};
+
+/* If this flag is set then this algorithm uses
+ * a driver only available in kernel (software drivers,
+ * or drivers based on instruction sets do not set this flag).
+ *
+ * If multiple algorithms are involved (as in AEAD case), then
+ * if one of them is kernel-driver-only this flag will be set.
+ */
+#define SIOP_FLAG_KERNEL_DRIVER_ONLY 1
+
+#define COP_ENCRYPT 0
+#define COP_DECRYPT 1
+
+/* input of CIOCCRYPT */
+struct crypt_op {
+ __u32 ses; /* session identifier */
+ __u16 op; /* COP_ENCRYPT or COP_DECRYPT */
+ __u16 flags; /* see COP_FLAG_* */
+ __u32 len; /* length of source data */
+ __u8 __user *src; /* source data */
+ __u8 __user *dst; /* pointer to output data */
+ /* pointer to output data for hash/MAC operations */
+ __u8 __user *mac;
+ /* initialization vector for encryption operations */
+ __u8 __user *iv;
+};
+
+/* input of CIOCAUTHCRYPT */
+struct crypt_auth_op {
+ __u32 ses; /* session identifier */
+ __u16 op; /* COP_ENCRYPT or COP_DECRYPT */
+ __u16 flags; /* see COP_FLAG_AEAD_* */
+ __u32 len; /* length of source data */
+ __u32 auth_len; /* length of auth data */
+ __u8 __user *auth_src; /* authenticated-only data */
+
+ /* The current implementation is more efficient if data are
+ * encrypted in-place (src==dst). */
+ __u8 __user *src; /* data to be encrypted and authenticated */
+ __u8 __user *dst; /* pointer to output data. Must have
+ * space for tag. For TLS this should be at least
+ * len + tag_size + block_size for padding */
+
+ __u8 __user *tag; /* where the tag will be copied to. TLS mode
+ * doesn't use that as tag is copied to dst.
+ * SRTP mode copies tag there. */
+ __u32 tag_len; /* the length of the tag. Use zero for digest size or max tag. */
+
+ /* initialization vector for encryption operations */
+ __u8 __user *iv;
+ __u32 iv_len;
+};
+
+/* In plain AEAD mode the following are required:
+ * flags : 0
+ * iv : the initialization vector (12 bytes)
+ * auth_len: the length of the data to be authenticated
+ * auth_src: the data to be authenticated
+ * len : length of data to be encrypted
+ * src : the data to be encrypted
+ * dst : space to hold encrypted data. It must have
+ * at least a size of len + tag_size.
+ * tag_size: the size of the desired authentication tag or zero to use
+ * the maximum tag output.
+ *
+ * Note tag isn't being used because the Linux AEAD interface
+ * copies the tag just after data.
+ */
+
+/* In TLS mode (used for CBC ciphers that required padding)
+ * the following are required:
+ * flags : COP_FLAG_AEAD_TLS_TYPE
+ * iv : the initialization vector
+ * auth_len: the length of the data to be authenticated only
+ * len : length of data to be encrypted
+ * auth_src: the data to be authenticated
+ * src : the data to be encrypted
+ * dst : space to hold encrypted data (preferably in-place). It must have
+ * at least a size of len + tag_size + blocksize.
+ * tag_size: the size of the desired authentication tag or zero to use
+ * the default mac output.
+ *
+ * Note that the padding used is the minimum padding.
+ */
+
+/* In SRTP mode the following are required:
+ * flags : COP_FLAG_AEAD_SRTP_TYPE
+ * iv : the initialization vector
+ * auth_len: the length of the data to be authenticated. This must
+ * include the SRTP header + SRTP payload (data to be encrypted) + rest
+ *
+ * len : length of data to be encrypted
+ * auth_src: pointer the data to be authenticated. Should point at the same buffer as src.
+ * src : pointer to the data to be encrypted.
+ * dst : This is mandatory to be the same as src (in-place only).
+ * tag_size: the size of the desired authentication tag or zero to use
+ * the default mac output.
+ * tag : Pointer to an address where the authentication tag will be copied.
+ */
+
+
+/* struct crypt_op flags */
+
+#define COP_FLAG_NONE (0 << 0) /* totally no flag */
+#define COP_FLAG_UPDATE (1 << 0) /* multi-update hash mode */
+#define COP_FLAG_FINAL (1 << 1) /* multi-update final hash mode */
+#define COP_FLAG_WRITE_IV (1 << 2) /* update the IV during operation */
+#define COP_FLAG_NO_ZC (1 << 3) /* do not zero-copy */
+#define COP_FLAG_AEAD_TLS_TYPE (1 << 4) /* authenticate and encrypt using the
+ * TLS protocol rules */
+#define COP_FLAG_AEAD_SRTP_TYPE (1 << 5) /* authenticate and encrypt using the
+ * SRTP protocol rules */
+#define COP_FLAG_RESET (1 << 6) /* multi-update reset the state.
+ * should be used in combination
+ * with COP_FLAG_UPDATE */
+
+
+#define COP_FLAG_ZC (1 << 10)
+
+/* Stuff for bignum arithmetic and public key
+ * cryptography - not supported yet by linux
+ * cryptodev.
+ */
+
+#define CRYPTO_ALG_FLAG_SUPPORTED 1
+#define CRYPTO_ALG_FLAG_RNG_ENABLE 2
+#define CRYPTO_ALG_FLAG_DSA_SHA 4
+
+struct crparam {
+ __u8 *crp_p;
+ __u32 crp_nbits;
+};
+
+#define CRK_MAXPARAM 8
+
+/* input of CIOCKEY */
+struct crypt_kop {
+ __u32 crk_op; /* cryptodev_crk_op_t */
+ __u32 crk_status;
+ __u16 crk_iparams;
+ __u16 crk_oparams;
+ __u32 crk_pad1;
+ struct crparam crk_param[CRK_MAXPARAM];
+};
+
+enum cryptodev_crk_op_t {
+ CRK_MOD_EXP = 0,
+ CRK_MOD_EXP_CRT = 1,
+ CRK_DSA_SIGN = 2,
+ CRK_DSA_VERIFY = 3,
+ CRK_DH_COMPUTE_KEY = 4,
+ CRK_ALGORITHM_ALL
+};
+
+/* input of CIOCCPHASH
+ * dst_ses : destination session identifier
+ * src_ses : source session identifier
+ * dst_ses must have been created with CIOGSESSION first
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+struct cphash_op {
+ __u32 dst_ses;
+ __u32 src_ses;
+};
+#endif
+
+#define CRK_ALGORITHM_MAX (CRK_ALGORITHM_ALL-1)
+
+/* features to be queried with CIOCASYMFEAT ioctl
+ */
+#define CRF_MOD_EXP (1 << CRK_MOD_EXP)
+#define CRF_MOD_EXP_CRT (1 << CRK_MOD_EXP_CRT)
+#define CRF_DSA_SIGN (1 << CRK_DSA_SIGN)
+#define CRF_DSA_VERIFY (1 << CRK_DSA_VERIFY)
+#define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY)
+
+
+/* ioctl's. Compatible with old linux cryptodev.h
+ */
+#define CRIOGET _IOWR('c', 101, __u32)
+#define CIOCGSESSION _IOWR('c', 102, struct session_op)
+#define CIOCFSESSION _IOW('c', 103, __u32)
+#define CIOCCRYPT _IOWR('c', 104, struct crypt_op)
+#define CIOCKEY _IOWR('c', 105, struct crypt_kop)
+#define CIOCASYMFEAT _IOR('c', 106, __u32)
+#define CIOCGSESSINFO _IOWR('c', 107, struct session_info_op)
+
+/* to indicate that CRIOGET is not required in linux
+ */
+#define CRIOGET_NOT_NEEDED 1
+
+/* additional ioctls for AEAD */
+#define CIOCAUTHCRYPT _IOWR('c', 109, struct crypt_auth_op)
+
+/* additional ioctls for asynchronous operation.
+ * These are conditionally enabled since version 1.6.
+ */
+#define CIOCASYNCCRYPT _IOW('c', 110, struct crypt_op)
+#define CIOCASYNCFETCH _IOR('c', 111, struct crypt_op)
+
+/* additional ioctl for copying of hash/mac session state data
+ * between sessions.
+ * The cphash_op parameter should contain the session id of
+ * the source and destination sessions. Both sessions
+ * must have been created with CIOGSESSION.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
+#define CIOCCPHASH _IOW('c', 112, struct cphash_op)
+#endif
+
+#endif /* L_CRYPTODEV_H */
diff --git a/drivers/cryptodev-linux-master/cryptodev_int.h b/drivers/cryptodev-linux-master/cryptodev_int.h
new file mode 100644
index 00000000..d7660fac
--- /dev/null
+++ b/drivers/cryptodev-linux-master/cryptodev_int.h
@@ -0,0 +1,145 @@
+/* cipher stuff */
+#ifndef CRYPTODEV_INT_H
+# define CRYPTODEV_INT_H
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
+# define reinit_completion(x) INIT_COMPLETION(*(x))
+#endif
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/scatterlist.h>
+#include <crypto/cryptodev.h>
+#include <crypto/aead.h>
+
+#define PFX "cryptodev: "
+#define dprintk(level, severity, format, a...) \
+ do { \
+ if (level <= cryptodev_verbosity) \
+ printk(severity PFX "%s[%u] (%s:%u): " format "\n", \
+ current->comm, current->pid, \
+ __func__, __LINE__, \
+ ##a); \
+ } while (0)
+#define derr(level, format, a...) dprintk(level, KERN_ERR, format, ##a)
+#define dwarning(level, format, a...) dprintk(level, KERN_WARNING, format, ##a)
+#define dinfo(level, format, a...) dprintk(level, KERN_INFO, format, ##a)
+#define ddebug(level, format, a...) dprintk(level, KERN_DEBUG, format, ##a)
+
+
+extern int cryptodev_verbosity;
+
+struct fcrypt {
+ struct list_head list;
+ struct mutex sem;
+};
+
+/* compatibility stuff */
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+/* input of CIOCGSESSION */
+struct compat_session_op {
+ /* Specify either cipher or mac
+ */
+ uint32_t cipher; /* cryptodev_crypto_op_t */
+ uint32_t mac; /* cryptodev_crypto_op_t */
+
+ uint32_t keylen;
+ compat_uptr_t key; /* pointer to key data */
+ uint32_t mackeylen;
+ compat_uptr_t mackey; /* pointer to mac key data */
+
+ uint32_t ses; /* session identifier */
+};
+
+/* input of CIOCCRYPT */
+struct compat_crypt_op {
+ uint32_t ses; /* session identifier */
+ uint16_t op; /* COP_ENCRYPT or COP_DECRYPT */
+ uint16_t flags; /* see COP_FLAG_* */
+ uint32_t len; /* length of source data */
+ compat_uptr_t src; /* source data */
+ compat_uptr_t dst; /* pointer to output data */
+ compat_uptr_t mac;/* pointer to output data for hash/MAC operations */
+ compat_uptr_t iv;/* initialization vector for encryption operations */
+};
+
+/* compat ioctls, defined for the above structs */
+#define COMPAT_CIOCGSESSION _IOWR('c', 102, struct compat_session_op)
+#define COMPAT_CIOCCRYPT _IOWR('c', 104, struct compat_crypt_op)
+#define COMPAT_CIOCASYNCCRYPT _IOW('c', 107, struct compat_crypt_op)
+#define COMPAT_CIOCASYNCFETCH _IOR('c', 108, struct compat_crypt_op)
+
+#endif /* CONFIG_COMPAT */
+
+/* kernel-internal extension to struct crypt_op */
+struct kernel_crypt_op {
+ struct crypt_op cop;
+
+ int ivlen;
+ __u8 iv[EALG_MAX_BLOCK_LEN];
+
+ int digestsize;
+ uint8_t hash_output[AALG_MAX_RESULT_LEN];
+
+ struct task_struct *task;
+ struct mm_struct *mm;
+};
+
+struct kernel_crypt_auth_op {
+ struct crypt_auth_op caop;
+
+ int dst_len; /* based on src_len + pad + tag */
+ int ivlen;
+ __u8 iv[EALG_MAX_BLOCK_LEN];
+
+ struct task_struct *task;
+ struct mm_struct *mm;
+};
+
+/* auth */
+
+int kcaop_from_user(struct kernel_crypt_auth_op *kcop,
+ struct fcrypt *fcr, void __user *arg);
+int kcaop_to_user(struct kernel_crypt_auth_op *kcaop,
+ struct fcrypt *fcr, void __user *arg);
+int crypto_auth_run(struct fcrypt *fcr, struct kernel_crypt_auth_op *kcaop);
+int crypto_run(struct fcrypt *fcr, struct kernel_crypt_op *kcop);
+
+#include <cryptlib.h>
+
+/* other internal structs */
+struct csession {
+ struct list_head entry;
+ struct mutex sem;
+ struct cipher_data cdata;
+ struct hash_data hdata;
+ uint32_t sid;
+ uint32_t alignmask;
+
+ unsigned int array_size;
+ unsigned int used_pages; /* the number of pages that are used */
+ /* the number of pages marked as NOT-writable; they preceed writeables */
+ unsigned int readonly_pages;
+ struct page **pages;
+ struct scatterlist *sg;
+};
+
+struct csession *crypto_get_session_by_sid(struct fcrypt *fcr, uint32_t sid);
+
+static inline void crypto_put_session(struct csession *ses_ptr)
+{
+ mutex_unlock(&ses_ptr->sem);
+}
+int adjust_sg_array(struct csession *ses, int pagecount);
+
+#endif /* CRYPTODEV_INT_H */
diff --git a/drivers/cryptodev-linux-master/examples/aes-gcm.c b/drivers/cryptodev-linux-master/examples/aes-gcm.c
new file mode 100644
index 00000000..6791f4eb
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/aes-gcm.c
@@ -0,0 +1,139 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "aes-gcm.h"
+
+int aes_gcm_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size)
+{
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->cfd = cfd;
+
+ ctx->sess.cipher = CRYPTO_AES_GCM;
+ ctx->sess.keylen = key_size;
+ ctx->sess.key = (void*)key;
+ if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return -1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = ctx->sess.ses;
+ if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return -1;
+ }
+ printf("Got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+ printf("Note: This is not an accelerated cipher\n");
+ }
+ /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
+ ctx->alignmask = siop.alignmask;
+#endif
+ return 0;
+}
+
+void aes_gcm_ctx_deinit(struct cryptodev_ctx* ctx)
+{
+ if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+}
+
+int
+aes_gcm_encrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ const void* plaintext, void* ciphertext, size_t size)
+{
+ struct crypt_auth_op cryp;
+ void* p;
+
+ /* check plaintext and ciphertext alignment */
+ if (ctx->alignmask) {
+ p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
+ if (plaintext != p) {
+ fprintf(stderr, "plaintext is not aligned\n");
+ return -1;
+ }
+
+ p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
+ if (ciphertext != p) {
+ fprintf(stderr, "ciphertext is not aligned\n");
+ return -1;
+ }
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.iv = (void*)iv;
+ cryp.op = COP_ENCRYPT;
+ cryp.auth_len = auth_size;
+ cryp.auth_src = (void*)auth;
+ cryp.len = size;
+ cryp.src = (void*)plaintext;
+ cryp.dst = ciphertext;
+ if (ioctl(ctx->cfd, CIOCAUTHCRYPT, &cryp)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+aes_gcm_decrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ const void* ciphertext, void* plaintext, size_t size)
+{
+ struct crypt_auth_op cryp;
+ void* p;
+
+ /* check plaintext and ciphertext alignment */
+ if (ctx->alignmask) {
+ p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
+ if (plaintext != p) {
+ fprintf(stderr, "plaintext is not aligned\n");
+ return -1;
+ }
+
+ p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
+ if (ciphertext != p) {
+ fprintf(stderr, "ciphertext is not aligned\n");
+ return -1;
+ }
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.iv = (void*)iv;
+ cryp.op = COP_DECRYPT;
+ cryp.auth_len = auth_size;
+ cryp.auth_src = (void*)auth;
+ cryp.len = size;
+ cryp.src = (void*)ciphertext;
+ cryp.dst = plaintext;
+ if (ioctl(ctx->cfd, CIOCAUTHCRYPT, &cryp)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/examples/aes-gcm.h b/drivers/cryptodev-linux-master/examples/aes-gcm.h
new file mode 100644
index 00000000..1ddc5fe4
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/aes-gcm.h
@@ -0,0 +1,28 @@
+#ifndef AES_H
+# define AES_H
+
+#include <stdint.h>
+
+struct cryptodev_ctx {
+ int cfd;
+ struct session_op sess;
+ uint16_t alignmask;
+};
+
+#define AES_BLOCK_SIZE 16
+
+int aes_gcm_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size);
+void aes_gcm_ctx_deinit();
+
+/* Note that encryption assumes that ciphertext has enough size
+ * for the tag to be appended. In decryption the tag is assumed
+ * to be the last bytes of ciphertext.
+ */
+int aes_gcm_encrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ const void* plaintext, void* ciphertext, size_t size);
+int aes_gcm_decrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ const void* ciphertext, void* plaintext, size_t size);
+
+#endif
diff --git a/drivers/cryptodev-linux-master/examples/aes-sha1.c b/drivers/cryptodev-linux-master/examples/aes-sha1.c
new file mode 100644
index 00000000..e93e3c44
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/aes-sha1.c
@@ -0,0 +1,139 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "aes-sha1.h"
+
+/* This is the TLS version of AES-CBC with HMAC-SHA1.
+ */
+
+int aes_sha1_ctx_init(struct cryptodev_ctx* ctx, int cfd,
+ const uint8_t *key, unsigned int key_size,
+ const uint8_t *mac_key, unsigned int mac_key_size)
+{
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->cfd = cfd;
+
+ ctx->sess.cipher = CRYPTO_AES_CBC;
+ ctx->sess.keylen = key_size;
+ ctx->sess.key = (void*)key;
+
+ ctx->sess.mac = CRYPTO_SHA1_HMAC;
+ ctx->sess.mackeylen = mac_key_size;
+ ctx->sess.mackey = (void*)mac_key;
+
+ if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return -1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = ctx->sess.ses;
+ if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return -1;
+ }
+ printf("Got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+ printf("Note: This is not an accelerated cipher\n");
+ }
+ /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
+ ctx->alignmask = siop.alignmask;
+#endif
+ return 0;
+}
+
+void aes_sha1_ctx_deinit(struct cryptodev_ctx* ctx)
+{
+ if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+}
+
+int
+aes_sha1_encrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ void* plaintext, size_t size)
+{
+ struct crypt_auth_op cryp;
+ void* p;
+
+ /* check plaintext and ciphertext alignment */
+ if (ctx->alignmask) {
+ p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
+ if (plaintext != p) {
+ fprintf(stderr, "plaintext is not aligned\n");
+ return -1;
+ }
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.iv = (void*)iv;
+ cryp.op = COP_ENCRYPT;
+ cryp.auth_len = auth_size;
+ cryp.auth_src = (void*)auth;
+ cryp.len = size;
+ cryp.src = (void*)plaintext;
+ cryp.dst = plaintext;
+ cryp.flags = COP_FLAG_AEAD_TLS_TYPE;
+ if (ioctl(ctx->cfd, CIOCAUTHCRYPT, &cryp)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+aes_sha1_decrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ void* ciphertext, size_t size)
+{
+ struct crypt_auth_op cryp;
+ void* p;
+
+ /* check plaintext and ciphertext alignment */
+ if (ctx->alignmask) {
+ p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
+ if (ciphertext != p) {
+ fprintf(stderr, "ciphertext is not aligned\n");
+ return -1;
+ }
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.iv = (void*)iv;
+ cryp.op = COP_DECRYPT;
+ cryp.auth_len = auth_size;
+ cryp.auth_src = (void*)auth;
+ cryp.len = size;
+ cryp.src = (void*)ciphertext;
+ cryp.dst = ciphertext;
+ cryp.flags = COP_FLAG_AEAD_TLS_TYPE;
+ if (ioctl(ctx->cfd, CIOCAUTHCRYPT, &cryp)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/examples/aes-sha1.h b/drivers/cryptodev-linux-master/examples/aes-sha1.h
new file mode 100644
index 00000000..a07334cf
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/aes-sha1.h
@@ -0,0 +1,31 @@
+#ifndef AES_H
+# define AES_H
+
+#include <stdint.h>
+
+struct cryptodev_ctx {
+ int cfd;
+ struct session_op sess;
+ uint16_t alignmask;
+};
+
+#define AES_BLOCK_SIZE 16
+
+int aes_sha1_ctx_init(struct cryptodev_ctx* ctx, int cfd,
+ const uint8_t *key, unsigned int key_size,
+ const uint8_t *mac_key, unsigned int mac_key_size);
+void aes_sha1_ctx_deinit();
+
+/* Note that encryption assumes that ciphertext has enough size
+ * for the tag and padding to be appended.
+ *
+ * Only in-place encryption and decryption are supported.
+ */
+int aes_sha1_encrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ void* plaintext, size_t size);
+int aes_sha1_decrypt(struct cryptodev_ctx* ctx, const void* iv,
+ const void* auth, size_t auth_size,
+ void* ciphertext, size_t size);
+
+#endif
diff --git a/drivers/cryptodev-linux-master/examples/aes.c b/drivers/cryptodev-linux-master/examples/aes.c
new file mode 100644
index 00000000..02f7613b
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/aes.c
@@ -0,0 +1,242 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "aes.h"
+
+#define KEY_SIZE 16
+
+
+int aes_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size)
+{
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->cfd = cfd;
+
+ ctx->sess.cipher = CRYPTO_AES_CBC;
+ ctx->sess.keylen = key_size;
+ ctx->sess.key = (void*)key;
+ if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return -1;
+ }
+
+#ifdef CIOCGSESSINFO
+ memset(&siop, 0, sizeof(siop));
+
+ siop.ses = ctx->sess.ses;
+ if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return -1;
+ }
+ printf("Got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+ printf("Note: This is not an accelerated cipher\n");
+ }
+ /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
+ ctx->alignmask = siop.alignmask;
+#endif
+ return 0;
+}
+
+void aes_ctx_deinit(struct cryptodev_ctx* ctx)
+{
+ if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+}
+
+int
+aes_encrypt(struct cryptodev_ctx* ctx, const void* iv, const void* plaintext, void* ciphertext, size_t size)
+{
+ struct crypt_op cryp;
+ void* p;
+
+ /* check plaintext and ciphertext alignment */
+ if (ctx->alignmask) {
+ p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
+ if (plaintext != p) {
+ fprintf(stderr, "plaintext is not aligned\n");
+ return -1;
+ }
+
+ p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
+ if (ciphertext != p) {
+ fprintf(stderr, "ciphertext is not aligned\n");
+ return -1;
+ }
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.len = size;
+ cryp.src = (void*)plaintext;
+ cryp.dst = ciphertext;
+ cryp.iv = (void*)iv;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+aes_decrypt(struct cryptodev_ctx* ctx, const void* iv, const void* ciphertext, void* plaintext, size_t size)
+{
+ struct crypt_op cryp;
+ void* p;
+
+ /* check plaintext and ciphertext alignment */
+ if (ctx->alignmask) {
+ p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
+ if (plaintext != p) {
+ fprintf(stderr, "plaintext is not aligned\n");
+ return -1;
+ }
+
+ p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
+ if (ciphertext != p) {
+ fprintf(stderr, "ciphertext is not aligned\n");
+ return -1;
+ }
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.len = size;
+ cryp.src = (void*)ciphertext;
+ cryp.dst = plaintext;
+ cryp.iv = (void*)iv;
+ cryp.op = COP_DECRYPT;
+ if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int test_aes(int cfd)
+{
+ char plaintext1_raw[AES_BLOCK_SIZE + 63], *plaintext1;
+ char ciphertext1[AES_BLOCK_SIZE] = { 0xdf, 0x55, 0x6a, 0x33, 0x43, 0x8d, 0xb8, 0x7b, 0xc4, 0x1b, 0x17, 0x52, 0xc5, 0x5e, 0x5e, 0x49 };
+ char iv1[AES_BLOCK_SIZE];
+ uint8_t key1[KEY_SIZE] = { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ char plaintext2_data[AES_BLOCK_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 };
+ char plaintext2_raw[AES_BLOCK_SIZE + 63], *plaintext2;
+ char ciphertext2[AES_BLOCK_SIZE] = { 0xb7, 0x97, 0x2b, 0x39, 0x41, 0xc4, 0x4b, 0x90, 0xaf, 0xa7, 0xb2, 0x64, 0xbf, 0xba, 0x73, 0x87 };
+ char iv2[AES_BLOCK_SIZE];
+ uint8_t key2[KEY_SIZE];
+ struct cryptodev_ctx ctx;
+
+ aes_ctx_init(&ctx, cfd, key1, sizeof(key1));
+
+ if (ctx.alignmask)
+ plaintext1 = (char *)(((unsigned long)plaintext1_raw + ctx.alignmask) & ~ctx.alignmask);
+ else
+ plaintext1 = plaintext1_raw;
+
+ memset(plaintext1, 0x0, AES_BLOCK_SIZE);
+ memset(iv1, 0x0, sizeof(iv1));
+
+ aes_encrypt(&ctx, iv1, plaintext1, plaintext1, AES_BLOCK_SIZE);
+
+ /* Verify the result */
+ if (memcmp(plaintext1, ciphertext1, AES_BLOCK_SIZE) != 0) {
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ return -1;
+ }
+
+ aes_ctx_deinit(&ctx);
+
+ /* Test 2 */
+
+ memset(key2, 0x0, sizeof(key2));
+ memset(iv2, 0x0, sizeof(iv2));
+
+ aes_ctx_init(&ctx, cfd, key2, sizeof(key2));
+
+ if (ctx.alignmask) {
+ plaintext2 = (char *)(((unsigned long)plaintext2_raw + ctx.alignmask) & ~ctx.alignmask);
+ } else {
+ plaintext2 = plaintext2_raw;
+ }
+ memcpy(plaintext2, plaintext2_data, AES_BLOCK_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ aes_encrypt(&ctx, iv2, plaintext2, plaintext2, AES_BLOCK_SIZE);
+
+ /* Verify the result */
+ if (memcmp(plaintext2, ciphertext2, AES_BLOCK_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
+ printf("%02x ", plaintext2[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
+ printf("%02x ", ciphertext2[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ aes_ctx_deinit(&ctx);
+
+ printf("AES Test passed\n");
+
+ return 0;
+}
+
+int
+main()
+{
+ int cfd = -1;
+
+ /* Open the crypto device */
+ cfd = open("/dev/crypto", O_RDWR, 0);
+ if (cfd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+ if (test_aes(cfd))
+ return 1;
+
+ /* Close the original descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/examples/aes.h b/drivers/cryptodev-linux-master/examples/aes.h
new file mode 100644
index 00000000..ade90c92
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/aes.h
@@ -0,0 +1,19 @@
+#ifndef AES_H
+# define AES_H
+
+#include <stdint.h>
+
+struct cryptodev_ctx {
+ int cfd;
+ struct session_op sess;
+ uint16_t alignmask;
+};
+
+#define AES_BLOCK_SIZE 16
+
+int aes_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size);
+void aes_ctx_deinit();
+int aes_encrypt(struct cryptodev_ctx* ctx, const void* iv, const void* plaintext, void* ciphertext, size_t size);
+int aes_decrypt(struct cryptodev_ctx* ctx, const void* iv, const void* ciphertext, void* plaintext, size_t size);
+
+#endif
diff --git a/drivers/cryptodev-linux-master/examples/sha-copy.c b/drivers/cryptodev-linux-master/examples/sha-copy.c
new file mode 100644
index 00000000..6bf8d2f8
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/sha-copy.c
@@ -0,0 +1,240 @@
+/*
+ * Demo on how to use /dev/crypto device for calculating a hash
+ * at once, using init->hash, and compare it to using:
+ * using init->update->final, and init->update->copy-> update -> final
+ * init->----\> update -> final
+ *
+ * Placed under public domain.
+ *
+ */
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "sha-copy.h"
+
+int sha_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size)
+{
+ struct session_info_op siop;
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->cfd = cfd;
+
+ if (key == NULL)
+ ctx->sess.mac = CRYPTO_SHA1;
+ else {
+ ctx->sess.mac = CRYPTO_SHA1_HMAC;
+ ctx->sess.mackeylen = key_size;
+ ctx->sess.mackey = (void*)key;
+ }
+ if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return -1;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "sha_ctx_init: cfd=%d, ses=%04x\n", ctx->cfd, ctx->sess.ses);
+#endif
+
+ siop.ses = ctx->sess.ses;
+ if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return -1;
+ }
+ printf("Got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+ printf("Note: This is not an accelerated cipher\n");
+ }
+ return 0;
+}
+
+static int sha_call_crypt(struct cryptodev_ctx* ctx, const void* text,
+ size_t size, void *digest, unsigned int flags)
+{
+ struct crypt_op cryp;
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Fill out the fields with text, size, digest result and flags */
+ cryp.ses = ctx->sess.ses;
+ cryp.len = size;
+ cryp.src = (void*)text;
+ cryp.mac = digest;
+ cryp.flags = flags;
+#ifdef DEBUG
+ fprintf(stderr, "sha_call_crypt: cfd=%d, ses=%04x, CIOCCRYPT(len=%d, src='%s', flags=%04x)\n",
+ ctx->cfd, ctx->sess.ses, cryp.len, (char *)cryp.src, cryp.flags);
+#endif
+ return ioctl(ctx->cfd, CIOCCRYPT, &cryp);
+}
+
+int sha_hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest)
+{
+#ifdef DEBUG
+ fprintf(stderr, "sha_hash: cfd=%d, ses=%04x, text='%s', size=%ld\n",
+ ctx->cfd, ctx->sess.ses, (char *) text, size);
+#endif
+ if (sha_call_crypt(ctx, text, size, digest, 0)) {
+ perror("sha_hash: ioctl(CIOCCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+int sha_update(struct cryptodev_ctx* ctx, const void* text, size_t size)
+{
+#ifdef DEBUG
+ fprintf(stderr, "sha_update: cfd=%d, ses=%04x, text='%s', size=%ld\n",
+ ctx->cfd, ctx->sess.ses, (char *) text, size);
+#endif
+ if (sha_call_crypt(ctx, text, size, NULL, COP_FLAG_UPDATE)) {
+ perror("sha_update: ioctl(CIOCCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+int sha_copy(struct cryptodev_ctx* to_ctx, const struct cryptodev_ctx* from_ctx)
+{
+ struct cphash_op cphash;
+
+#ifdef DEBUG
+ fprintf(stderr, "sha_copy: from= cfd=%d, ses=%04x\n"
+ " to= cfd=%d, ses=%04x\n",
+ from_ctx->cfd, from_ctx->sess.ses, to_ctx->cfd, to_ctx->sess.ses);
+#endif
+ memset(&cphash, 0, sizeof(cphash));
+
+ cphash.src_ses = from_ctx->sess.ses;
+ cphash.dst_ses = to_ctx->sess.ses;
+ if (ioctl(to_ctx->cfd, CIOCCPHASH, &cphash)) {
+ perror("ioctl(CIOCCPHASH)");
+ return -1;
+ }
+
+ return 0;
+}
+
+int sha_final(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest)
+{
+#ifdef DEBUG
+ fprintf(stderr, "sha_final: cfd=%d, ses=%04x, text='%s', size=%ld\n",
+ ctx->cfd, ctx->sess.ses, (char *) text, size);
+#endif
+ if (sha_call_crypt(ctx, text, size, digest, COP_FLAG_FINAL)) {
+ perror("sha_final: ioctl(CIOCCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+void sha_ctx_deinit(struct cryptodev_ctx* ctx)
+{
+#ifdef DEBUG
+ fprintf(stderr, "sha_ctx_deinit: cfd=%d, ses=%04x\n", ctx->cfd, ctx->sess.ses);
+#endif
+ if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+}
+
+static int print_digest(uint8_t *digest, uint8_t *expected)
+{
+ int i;
+
+ if (memcmp(digest, expected, 20) != 0) {
+ fprintf(stderr, "SHA1 hashing failed\n");
+ }
+
+ printf("digest: ");
+ for (i = 0; i < 20; i++) {
+ printf("%02x:", *digest);
+ digest++;
+ }
+ printf("\n");
+}
+
+int
+main()
+{
+ int cfd = -1;
+ struct cryptodev_ctx ctx1, ctx2;
+ uint8_t digest[20];
+ char text[] = "The quick brown fox jumps over the lazy dog";
+ char text1[] = "The quick brown fox";
+ char text2[] = " jumps over the lazy dog";
+ char text3[] = " jumps over the lazy dogs";
+ uint8_t expected[] = "\x2f\xd4\xe1\xc6\x7a\x2d\x28\xfc\xed\x84\x9e\xe1\xbb\x76\xe7\x39\x1b\x93\xeb\x12";
+ uint8_t expected2[] = "\xf8\xc3\xc5\x41\x25\x7a\x6c\x31\xf6\xfb\xc6\x97\xa5\x0f\x46\xd9\xfc\x8b\xcc\x30";
+
+ /* Open the crypto device */
+ cfd = open("/dev/crypto", O_RDWR, 0);
+ if (cfd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ printf("Computing digest in one operation\n");
+ sha_ctx_init(&ctx1, cfd, NULL, 0);
+ sha_hash(&ctx1, text, strlen(text), digest);
+ sha_ctx_deinit(&ctx1);
+ print_digest(digest, expected);
+
+ printf("\n\nComputing digest using update/final\n");
+ sha_ctx_init(&ctx1, cfd, NULL, 0);
+ sha_update(&ctx1, text1, strlen(text1));
+ sha_final(&ctx1, text2, strlen(text2), digest);
+ sha_ctx_deinit(&ctx1);
+ print_digest(digest, expected);
+
+ printf("\n\nComputing digest using update/copy/final\n");
+ sha_ctx_init(&ctx1, cfd, NULL, 0);
+ sha_update(&ctx1, text1, strlen(text1));
+ sha_ctx_init(&ctx2, cfd, NULL, 0);
+ sha_copy(&ctx2, &ctx1);
+ printf("\nOriginal operation:\n");
+ sha_update(&ctx1, text2, strlen(text2));
+ sha_final(&ctx1, NULL, 0, digest);
+ print_digest(digest, expected);
+ printf("\nCopied operation:\n");
+ sha_final(&ctx2, text2, strlen(text2), digest);
+ sha_ctx_deinit(&ctx1);
+ sha_ctx_deinit(&ctx2);
+ print_digest(digest, expected);
+
+ printf("\n\nComputing digest using update/copy/final with different texts\n");
+ sha_ctx_init(&ctx1, cfd, NULL, 0);
+ sha_update(&ctx1, text1, strlen(text1));
+ sha_ctx_init(&ctx2, cfd, NULL, 0);
+ sha_copy(&ctx2, &ctx1);
+ printf("\nOriginal operation, with original text:\n");
+ sha_update(&ctx1, text2, strlen(text2));
+ sha_final(&ctx1, NULL, 0, digest);
+ print_digest(digest, expected);
+ printf("\nCopied operation, with different text:\n");
+ sha_update(&ctx2, text3, strlen(text3));
+ sha_final(&ctx2, NULL, 0, digest);
+ sha_ctx_deinit(&ctx1);
+ sha_ctx_deinit(&ctx2);
+ print_digest(digest, expected2);
+
+ /* Close the original descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/examples/sha-copy.h b/drivers/cryptodev-linux-master/examples/sha-copy.h
new file mode 100644
index 00000000..8b2114e6
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/sha-copy.h
@@ -0,0 +1,18 @@
+#ifndef SHA_COPY_H
+#define SHA_COPY_H
+
+#include <stdint.h>
+
+struct cryptodev_ctx {
+ int cfd;
+ struct session_op sess;
+};
+
+int sha_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size);
+int sha_hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest);
+int sha_update(struct cryptodev_ctx* ctx, const void* text, size_t size);
+int sha_copy(struct cryptodev_ctx* to_ctx, const struct cryptodev_ctx* from_ctx);
+int sha_final(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest);
+void sha_ctx_deinit(struct cryptodev_ctx* ctx);
+
+#endif /* SHA_COPY_H */
diff --git a/drivers/cryptodev-linux-master/examples/sha.c b/drivers/cryptodev-linux-master/examples/sha.c
new file mode 100644
index 00000000..4f45a6b0
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/sha.c
@@ -0,0 +1,137 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "sha.h"
+
+int sha_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size)
+{
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->cfd = cfd;
+
+ if (key == NULL)
+ ctx->sess.mac = CRYPTO_SHA1;
+ else {
+ ctx->sess.mac = CRYPTO_SHA1_HMAC;
+ ctx->sess.mackeylen = key_size;
+ ctx->sess.mackey = (void*)key;
+ }
+ if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return -1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = ctx->sess.ses;
+ if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return -1;
+ }
+ printf("Got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)) {
+ printf("Note: This is not an accelerated cipher\n");
+ }
+ /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask);*/
+ ctx->alignmask = siop.alignmask;
+#endif
+ return 0;
+}
+
+void sha_ctx_deinit(struct cryptodev_ctx* ctx)
+{
+ if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+}
+
+int
+sha_hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest)
+{
+ struct crypt_op cryp;
+ void* p;
+
+ /* check text and ciphertext alignment */
+ if (ctx->alignmask) {
+ p = (void*)(((unsigned long)text + ctx->alignmask) & ~ctx->alignmask);
+ if (text != p) {
+ fprintf(stderr, "text is not aligned\n");
+ return -1;
+ }
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.len = size;
+ cryp.src = (void*)text;
+ cryp.mac = digest;
+ if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+main()
+{
+ int cfd = -1, i;
+ struct cryptodev_ctx ctx;
+ uint8_t digest[20];
+ char text[] = "The quick brown fox jumps over the lazy dog";
+ uint8_t expected[] = "\x2f\xd4\xe1\xc6\x7a\x2d\x28\xfc\xed\x84\x9e\xe1\xbb\x76\xe7\x39\x1b\x93\xeb\x12";
+
+ /* Open the crypto device */
+ cfd = open("/dev/crypto", O_RDWR, 0);
+ if (cfd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ sha_ctx_init(&ctx, cfd, NULL, 0);
+
+ sha_hash(&ctx, text, strlen(text), digest);
+
+ sha_ctx_deinit(&ctx);
+
+ printf("digest: ");
+ for (i = 0; i < 20; i++) {
+ printf("%02x:", digest[i]);
+ }
+ printf("\n");
+
+ if (memcmp(digest, expected, 20) != 0) {
+ fprintf(stderr, "SHA1 hashing failed\n");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/examples/sha.h b/drivers/cryptodev-linux-master/examples/sha.h
new file mode 100644
index 00000000..ed0b8cee
--- /dev/null
+++ b/drivers/cryptodev-linux-master/examples/sha.h
@@ -0,0 +1,16 @@
+#ifndef SHA_H
+# define SHA_H
+
+#include <stdint.h>
+
+struct cryptodev_ctx {
+ int cfd;
+ struct session_op sess;
+ uint16_t alignmask;
+};
+
+int sha_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t *key, unsigned int key_size);
+void sha_ctx_deinit();
+int sha_hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest);
+
+#endif
diff --git a/drivers/cryptodev-linux-master/ioctl.c b/drivers/cryptodev-linux-master/ioctl.c
new file mode 100644
index 00000000..3d332380
--- /dev/null
+++ b/drivers/cryptodev-linux-master/ioctl.c
@@ -0,0 +1,1227 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2004 Michal Ludvig <mludvig@logix.net.nz>, SuSE Labs
+ * Copyright (c) 2009,2010,2011 Nikos Mavrogiannopoulos <nmav@gnutls.org>
+ * Copyright (c) 2010 Phil Sutter
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Device /dev/crypto provides an interface for
+ * accessing kernel CryptoAPI algorithms (ciphers,
+ * hashes) from userspace programs.
+ *
+ * /dev/crypto interface was originally introduced in
+ * OpenBSD and this module attempts to keep the API.
+ *
+ */
+
+#include <crypto/hash.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/ioctl.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+#include <linux/pagemap.h>
+#include <linux/poll.h>
+#include <linux/uaccess.h>
+#include <crypto/cryptodev.h>
+#include <linux/scatterlist.h>
+#include <linux/rtnetlink.h>
+#include <crypto/authenc.h>
+
+#include <linux/sysctl.h>
+
+#include "cryptodev_int.h"
+#include "zc.h"
+#include "version.h"
+#include "cipherapi.h"
+
+MODULE_AUTHOR("Nikos Mavrogiannopoulos <nmav@gnutls.org>");
+MODULE_DESCRIPTION("CryptoDev driver");
+MODULE_LICENSE("GPL");
+
+/* ====== Compile-time config ====== */
+
+/* Default (pre-allocated) and maximum size of the job queue.
+ * These are free, pending and done items all together. */
+#define DEF_COP_RINGSIZE 16
+#define MAX_COP_RINGSIZE 64
+
+/* ====== Module parameters ====== */
+
+int cryptodev_verbosity;
+module_param(cryptodev_verbosity, int, 0644);
+MODULE_PARM_DESC(cryptodev_verbosity, "0: normal, 1: verbose, 2: debug");
+
+/* ====== CryptoAPI ====== */
+struct todo_list_item {
+ struct list_head __hook;
+ struct kernel_crypt_op kcop;
+ int result;
+};
+
+struct locked_list {
+ struct list_head list;
+ struct mutex lock;
+};
+
+struct crypt_priv {
+ struct fcrypt fcrypt;
+ struct locked_list free, todo, done;
+ int itemcount;
+ struct work_struct cryptask;
+ wait_queue_head_t user_waiter;
+};
+
+#define FILL_SG(sg, ptr, len) \
+ do { \
+ (sg)->page = virt_to_page(ptr); \
+ (sg)->offset = offset_in_page(ptr); \
+ (sg)->length = len; \
+ (sg)->dma_address = 0; \
+ } while (0)
+
+/* cryptodev's own workqueue, keeps crypto tasks from disturbing the force */
+static struct workqueue_struct *cryptodev_wq;
+
+/* Prepare session for future use. */
+static int
+crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
+{
+ struct csession *ses_new = NULL, *ses_ptr;
+ int ret = 0;
+ const char *alg_name = NULL;
+ const char *hash_name = NULL;
+ int hmac_mode = 1, stream = 0, aead = 0;
+ /*
+ * With composite aead ciphers, only ckey is used and it can cover all the
+ * structure space; otherwise both keys may be used simultaneously but they
+ * are confined to their spaces
+ */
+ struct {
+ uint8_t ckey[CRYPTO_CIPHER_MAX_KEY_LEN];
+ uint8_t mkey[CRYPTO_HMAC_MAX_KEY_LEN];
+ /* padding space for aead keys */
+ uint8_t pad[RTA_SPACE(sizeof(struct crypto_authenc_key_param))];
+ } keys;
+
+ /* Does the request make sense? */
+ if (unlikely(!sop->cipher && !sop->mac)) {
+ ddebug(1, "Both 'cipher' and 'mac' unset.");
+ return -EINVAL;
+ }
+
+ switch (sop->cipher) {
+ case 0:
+ break;
+ case CRYPTO_DES_CBC:
+ alg_name = "cbc(des)";
+ break;
+ case CRYPTO_3DES_CBC:
+ alg_name = "cbc(des3_ede)";
+ break;
+ case CRYPTO_BLF_CBC:
+ alg_name = "cbc(blowfish)";
+ break;
+ case CRYPTO_AES_CBC:
+ alg_name = "cbc(aes)";
+ break;
+ case CRYPTO_AES_ECB:
+ alg_name = "ecb(aes)";
+ break;
+ case CRYPTO_CAMELLIA_CBC:
+ alg_name = "cbc(camellia)";
+ break;
+ case CRYPTO_AES_CTR:
+ alg_name = "ctr(aes)";
+ stream = 1;
+ break;
+ case CRYPTO_AES_GCM:
+ alg_name = "gcm(aes)";
+ stream = 1;
+ aead = 1;
+ break;
+ case CRYPTO_TLS11_AES_CBC_HMAC_SHA1:
+ alg_name = "tls11(hmac(sha1),cbc(aes))";
+ stream = 0;
+ aead = 1;
+ break;
+ case CRYPTO_TLS12_AES_CBC_HMAC_SHA256:
+ alg_name = "tls12(hmac(sha256),cbc(aes))";
+ stream = 0;
+ aead = 1;
+ break;
+ case CRYPTO_NULL:
+ alg_name = "ecb(cipher_null)";
+ stream = 1;
+ break;
+ default:
+ ddebug(1, "bad cipher: %d", sop->cipher);
+ return -EINVAL;
+ }
+
+ switch (sop->mac) {
+ case 0:
+ break;
+ case CRYPTO_MD5_HMAC:
+ hash_name = "hmac(md5)";
+ break;
+ case CRYPTO_RIPEMD160_HMAC:
+ hash_name = "hmac(rmd160)";
+ break;
+ case CRYPTO_SHA1_HMAC:
+ hash_name = "hmac(sha1)";
+ break;
+ case CRYPTO_SHA2_224_HMAC:
+ hash_name = "hmac(sha224)";
+ break;
+
+ case CRYPTO_SHA2_256_HMAC:
+ hash_name = "hmac(sha256)";
+ break;
+ case CRYPTO_SHA2_384_HMAC:
+ hash_name = "hmac(sha384)";
+ break;
+ case CRYPTO_SHA2_512_HMAC:
+ hash_name = "hmac(sha512)";
+ break;
+
+ /* non-hmac cases */
+ case CRYPTO_MD5:
+ hash_name = "md5";
+ hmac_mode = 0;
+ break;
+ case CRYPTO_RIPEMD160:
+ hash_name = "rmd160";
+ hmac_mode = 0;
+ break;
+ case CRYPTO_SHA1:
+ hash_name = "sha1";
+ hmac_mode = 0;
+ break;
+ case CRYPTO_SHA2_224:
+ hash_name = "sha224";
+ hmac_mode = 0;
+ break;
+ case CRYPTO_SHA2_256:
+ hash_name = "sha256";
+ hmac_mode = 0;
+ break;
+ case CRYPTO_SHA2_384:
+ hash_name = "sha384";
+ hmac_mode = 0;
+ break;
+ case CRYPTO_SHA2_512:
+ hash_name = "sha512";
+ hmac_mode = 0;
+ break;
+ default:
+ ddebug(1, "bad mac: %d", sop->mac);
+ return -EINVAL;
+ }
+
+ /* Create a session and put it to the list. Zeroing the structure helps
+ * also with a single exit point in case of errors */
+ ses_new = kzalloc(sizeof(*ses_new), GFP_KERNEL);
+ if (!ses_new)
+ return -ENOMEM;
+
+ /* Set-up crypto transform. */
+ if (alg_name) {
+ unsigned int keylen;
+ ret = cryptodev_get_cipher_keylen(&keylen, sop, aead);
+ if (unlikely(ret < 0)) {
+ ddebug(1, "Setting key failed for %s-%zu.",
+ alg_name, (size_t)sop->keylen*8);
+ goto session_error;
+ }
+
+ ret = cryptodev_get_cipher_key(keys.ckey, sop, aead);
+ if (unlikely(ret < 0))
+ goto session_error;
+
+ ret = cryptodev_cipher_init(&ses_new->cdata, alg_name, keys.ckey,
+ keylen, stream, aead);
+ if (ret < 0) {
+ ddebug(1, "Failed to load cipher for %s", alg_name);
+ ret = -EINVAL;
+ goto session_error;
+ }
+ }
+
+ if (hash_name && aead == 0) {
+ if (unlikely(sop->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN)) {
+ ddebug(1, "Setting key failed for %s-%zu.",
+ hash_name, (size_t)sop->mackeylen*8);
+ ret = -EINVAL;
+ goto session_error;
+ }
+
+ if (sop->mackey && unlikely(copy_from_user(keys.mkey, sop->mackey,
+ sop->mackeylen))) {
+ ret = -EFAULT;
+ goto session_error;
+ }
+
+ ret = cryptodev_hash_init(&ses_new->hdata, hash_name, hmac_mode,
+ keys.mkey, sop->mackeylen);
+ if (ret != 0) {
+ ddebug(1, "Failed to load hash for %s", hash_name);
+ ret = -EINVAL;
+ goto session_error;
+ }
+
+ ret = cryptodev_hash_reset(&ses_new->hdata);
+ if (ret != 0) {
+ goto session_error;
+ }
+ }
+
+ ses_new->alignmask = max(ses_new->cdata.alignmask,
+ ses_new->hdata.alignmask);
+ ddebug(2, "got alignmask %d", ses_new->alignmask);
+
+ ses_new->array_size = DEFAULT_PREALLOC_PAGES;
+ ddebug(2, "preallocating for %d user pages", ses_new->array_size);
+ ses_new->pages = kzalloc(ses_new->array_size *
+ sizeof(struct page *), GFP_KERNEL);
+ ses_new->sg = kzalloc(ses_new->array_size *
+ sizeof(struct scatterlist), GFP_KERNEL);
+ if (ses_new->sg == NULL || ses_new->pages == NULL) {
+ ddebug(0, "Memory error");
+ ret = -ENOMEM;
+ goto session_error;
+ }
+
+ /* put the new session to the list */
+ get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
+ mutex_init(&ses_new->sem);
+
+ mutex_lock(&fcr->sem);
+restart:
+ list_for_each_entry(ses_ptr, &fcr->list, entry) {
+ /* Check for duplicate SID */
+ if (unlikely(ses_new->sid == ses_ptr->sid)) {
+ get_random_bytes(&ses_new->sid, sizeof(ses_new->sid));
+ /* Unless we have a broken RNG this
+ shouldn't loop forever... ;-) */
+ goto restart;
+ }
+ }
+
+ list_add(&ses_new->entry, &fcr->list);
+ mutex_unlock(&fcr->sem);
+
+ /* Fill in some values for the user. */
+ sop->ses = ses_new->sid;
+ return 0;
+
+ /* We count on ses_new to be initialized with zeroes
+ * Since hdata and cdata are embedded within ses_new, it follows that
+ * hdata->init and cdata->init are either zero or one as they have been
+ * initialized or not */
+session_error:
+ cryptodev_hash_deinit(&ses_new->hdata);
+ cryptodev_cipher_deinit(&ses_new->cdata);
+ kfree(ses_new->sg);
+ kfree(ses_new->pages);
+ kfree(ses_new);
+ return ret;
+}
+
+/* Everything that needs to be done when removing a session. */
+static inline void
+crypto_destroy_session(struct csession *ses_ptr)
+{
+ if (!mutex_trylock(&ses_ptr->sem)) {
+ ddebug(2, "Waiting for semaphore of sid=0x%08X", ses_ptr->sid);
+ mutex_lock(&ses_ptr->sem);
+ }
+ ddebug(2, "Removed session 0x%08X", ses_ptr->sid);
+ cryptodev_cipher_deinit(&ses_ptr->cdata);
+ cryptodev_hash_deinit(&ses_ptr->hdata);
+ ddebug(2, "freeing space for %d user pages", ses_ptr->array_size);
+ kfree(ses_ptr->pages);
+ kfree(ses_ptr->sg);
+ mutex_unlock(&ses_ptr->sem);
+ mutex_destroy(&ses_ptr->sem);
+ kfree(ses_ptr);
+}
+
+/* Look up a session by ID and remove. */
+static int
+crypto_finish_session(struct fcrypt *fcr, uint32_t sid)
+{
+ struct csession *tmp, *ses_ptr;
+ struct list_head *head;
+ int ret = 0;
+
+ mutex_lock(&fcr->sem);
+ head = &fcr->list;
+ list_for_each_entry_safe(ses_ptr, tmp, head, entry) {
+ if (ses_ptr->sid == sid) {
+ list_del(&ses_ptr->entry);
+ crypto_destroy_session(ses_ptr);
+ break;
+ }
+ }
+
+ if (unlikely(!ses_ptr)) {
+ derr(1, "Session with sid=0x%08X not found!", sid);
+ ret = -ENOENT;
+ }
+ mutex_unlock(&fcr->sem);
+
+ return ret;
+}
+
+/* Remove all sessions when closing the file */
+static int
+crypto_finish_all_sessions(struct fcrypt *fcr)
+{
+ struct csession *tmp, *ses_ptr;
+ struct list_head *head;
+
+ mutex_lock(&fcr->sem);
+
+ head = &fcr->list;
+ list_for_each_entry_safe(ses_ptr, tmp, head, entry) {
+ list_del(&ses_ptr->entry);
+ crypto_destroy_session(ses_ptr);
+ }
+ mutex_unlock(&fcr->sem);
+
+ return 0;
+}
+
+/* Look up session by session ID. The returned session is locked. */
+struct csession *
+crypto_get_session_by_sid(struct fcrypt *fcr, uint32_t sid)
+{
+ struct csession *ses_ptr, *retval = NULL;
+
+ if (unlikely(fcr == NULL))
+ return NULL;
+
+ mutex_lock(&fcr->sem);
+ list_for_each_entry(ses_ptr, &fcr->list, entry) {
+ if (ses_ptr->sid == sid) {
+ mutex_lock(&ses_ptr->sem);
+ retval = ses_ptr;
+ break;
+ }
+ }
+ mutex_unlock(&fcr->sem);
+
+ return retval;
+}
+
+#ifdef CIOCCPHASH
+/* Copy the hash state from one session to another */
+static int
+crypto_copy_hash_state(struct fcrypt *fcr, uint32_t dst_sid, uint32_t src_sid)
+{
+ struct csession *src_ses, *dst_ses;
+ int ret;
+
+ src_ses = crypto_get_session_by_sid(fcr, src_sid);
+ if (unlikely(src_ses == NULL)) {
+ derr(1, "Session with sid=0x%08X not found!", src_sid);
+ return -ENOENT;
+ }
+
+ dst_ses = crypto_get_session_by_sid(fcr, dst_sid);
+ if (unlikely(dst_ses == NULL)) {
+ derr(1, "Session with sid=0x%08X not found!", dst_sid);
+ crypto_put_session(src_ses);
+ return -ENOENT;
+ }
+
+ ret = cryptodev_hash_copy(&dst_ses->hdata, &src_ses->hdata);
+ crypto_put_session(src_ses);
+ crypto_put_session(dst_ses);
+ return ret;
+}
+#endif /* CIOCCPHASH */
+
+static void cryptask_routine(struct work_struct *work)
+{
+ struct crypt_priv *pcr = container_of(work, struct crypt_priv, cryptask);
+ struct todo_list_item *item;
+ LIST_HEAD(tmp);
+
+ /* fetch all pending jobs into the temporary list */
+ mutex_lock(&pcr->todo.lock);
+ list_cut_position(&tmp, &pcr->todo.list, pcr->todo.list.prev);
+ mutex_unlock(&pcr->todo.lock);
+
+ /* handle each job locklessly */
+ list_for_each_entry(item, &tmp, __hook) {
+ item->result = crypto_run(&pcr->fcrypt, &item->kcop);
+ if (unlikely(item->result))
+ derr(0, "crypto_run() failed: %d", item->result);
+ }
+
+ /* push all handled jobs to the done list at once */
+ mutex_lock(&pcr->done.lock);
+ list_splice_tail(&tmp, &pcr->done.list);
+ mutex_unlock(&pcr->done.lock);
+
+ /* wake for POLLIN */
+ wake_up_interruptible(&pcr->user_waiter);
+}
+
+/* ====== /dev/crypto ====== */
+
+static int
+cryptodev_open(struct inode *inode, struct file *filp)
+{
+ struct todo_list_item *tmp, *tmp_next;
+ struct crypt_priv *pcr;
+ int i;
+
+ pcr = kzalloc(sizeof(*pcr), GFP_KERNEL);
+ if (!pcr)
+ return -ENOMEM;
+ filp->private_data = pcr;
+
+ mutex_init(&pcr->fcrypt.sem);
+ mutex_init(&pcr->free.lock);
+ mutex_init(&pcr->todo.lock);
+ mutex_init(&pcr->done.lock);
+
+ INIT_LIST_HEAD(&pcr->fcrypt.list);
+ INIT_LIST_HEAD(&pcr->free.list);
+ INIT_LIST_HEAD(&pcr->todo.list);
+ INIT_LIST_HEAD(&pcr->done.list);
+
+ INIT_WORK(&pcr->cryptask, cryptask_routine);
+
+ init_waitqueue_head(&pcr->user_waiter);
+
+ for (i = 0; i < DEF_COP_RINGSIZE; i++) {
+ tmp = kzalloc(sizeof(struct todo_list_item), GFP_KERNEL);
+ if (!tmp)
+ goto err_ringalloc;
+ pcr->itemcount++;
+ ddebug(2, "allocated new item at %p", tmp);
+ list_add(&tmp->__hook, &pcr->free.list);
+ }
+
+ ddebug(2, "Cryptodev handle initialised, %d elements in queue",
+ DEF_COP_RINGSIZE);
+ return 0;
+
+/* In case of errors, free any memory allocated so far */
+err_ringalloc:
+ list_for_each_entry_safe(tmp, tmp_next, &pcr->free.list, __hook) {
+ list_del(&tmp->__hook);
+ kfree(tmp);
+ }
+ mutex_destroy(&pcr->done.lock);
+ mutex_destroy(&pcr->todo.lock);
+ mutex_destroy(&pcr->free.lock);
+ mutex_destroy(&pcr->fcrypt.sem);
+ kfree(pcr);
+ filp->private_data = NULL;
+ return -ENOMEM;
+}
+
+static int
+cryptodev_release(struct inode *inode, struct file *filp)
+{
+ struct crypt_priv *pcr = filp->private_data;
+ struct todo_list_item *item, *item_safe;
+ int items_freed = 0;
+
+ if (!pcr)
+ return 0;
+
+ cancel_work_sync(&pcr->cryptask);
+
+ list_splice_tail(&pcr->todo.list, &pcr->free.list);
+ list_splice_tail(&pcr->done.list, &pcr->free.list);
+
+ list_for_each_entry_safe(item, item_safe, &pcr->free.list, __hook) {
+ ddebug(2, "freeing item at %p", item);
+ list_del(&item->__hook);
+ kfree(item);
+ items_freed++;
+ }
+
+ if (items_freed != pcr->itemcount) {
+ derr(0, "freed %d items, but %d should exist!",
+ items_freed, pcr->itemcount);
+ }
+
+ crypto_finish_all_sessions(&pcr->fcrypt);
+
+ mutex_destroy(&pcr->done.lock);
+ mutex_destroy(&pcr->todo.lock);
+ mutex_destroy(&pcr->free.lock);
+ mutex_destroy(&pcr->fcrypt.sem);
+
+ kfree(pcr);
+ filp->private_data = NULL;
+
+ ddebug(2, "Cryptodev handle deinitialised, %d elements freed",
+ items_freed);
+ return 0;
+}
+
+static int
+clonefd(struct file *filp)
+{
+ int ret;
+ ret = get_unused_fd_flags(0);
+ if (ret >= 0) {
+ get_file(filp);
+ fd_install(ret, filp);
+ }
+
+ return ret;
+}
+
+#ifdef ENABLE_ASYNC
+/* enqueue a job for asynchronous completion
+ *
+ * returns:
+ * -EBUSY when there are no free queue slots left
+ * (and the number of slots has reached it MAX_COP_RINGSIZE)
+ * -EFAULT when there was a memory allocation error
+ * 0 on success */
+static int crypto_async_run(struct crypt_priv *pcr, struct kernel_crypt_op *kcop)
+{
+ struct todo_list_item *item = NULL;
+
+ if (unlikely(kcop->cop.flags & COP_FLAG_NO_ZC))
+ return -EINVAL;
+
+ mutex_lock(&pcr->free.lock);
+ if (likely(!list_empty(&pcr->free.list))) {
+ item = list_first_entry(&pcr->free.list,
+ struct todo_list_item, __hook);
+ list_del(&item->__hook);
+ } else if (pcr->itemcount < MAX_COP_RINGSIZE) {
+ pcr->itemcount++;
+ } else {
+ mutex_unlock(&pcr->free.lock);
+ return -EBUSY;
+ }
+ mutex_unlock(&pcr->free.lock);
+
+ if (unlikely(!item)) {
+ item = kzalloc(sizeof(struct todo_list_item), GFP_KERNEL);
+ if (unlikely(!item))
+ return -EFAULT;
+ dinfo(1, "increased item count to %d", pcr->itemcount);
+ }
+
+ memcpy(&item->kcop, kcop, sizeof(struct kernel_crypt_op));
+
+ mutex_lock(&pcr->todo.lock);
+ list_add_tail(&item->__hook, &pcr->todo.list);
+ mutex_unlock(&pcr->todo.lock);
+
+ queue_work(cryptodev_wq, &pcr->cryptask);
+ return 0;
+}
+
+/* get the first completed job from the "done" queue
+ *
+ * returns:
+ * -EBUSY if no completed jobs are ready (yet)
+ * the return value of crypto_run() otherwise */
+static int crypto_async_fetch(struct crypt_priv *pcr,
+ struct kernel_crypt_op *kcop)
+{
+ struct todo_list_item *item;
+ int retval;
+
+ mutex_lock(&pcr->done.lock);
+ if (list_empty(&pcr->done.list)) {
+ mutex_unlock(&pcr->done.lock);
+ return -EBUSY;
+ }
+ item = list_first_entry(&pcr->done.list, struct todo_list_item, __hook);
+ list_del(&item->__hook);
+ mutex_unlock(&pcr->done.lock);
+
+ memcpy(kcop, &item->kcop, sizeof(struct kernel_crypt_op));
+ retval = item->result;
+
+ mutex_lock(&pcr->free.lock);
+ list_add_tail(&item->__hook, &pcr->free.list);
+ mutex_unlock(&pcr->free.lock);
+
+ /* wake for POLLOUT */
+ wake_up_interruptible(&pcr->user_waiter);
+
+ return retval;
+}
+#endif
+
+/* this function has to be called from process context */
+static int fill_kcop_from_cop(struct kernel_crypt_op *kcop, struct fcrypt *fcr)
+{
+ struct crypt_op *cop = &kcop->cop;
+ struct csession *ses_ptr;
+ int rc;
+
+ /* this also enters ses_ptr->sem */
+ ses_ptr = crypto_get_session_by_sid(fcr, cop->ses);
+ if (unlikely(!ses_ptr)) {
+ derr(1, "invalid session ID=0x%08X", cop->ses);
+ return -EINVAL;
+ }
+ kcop->ivlen = cop->iv ? ses_ptr->cdata.ivsize : 0;
+ kcop->digestsize = 0; /* will be updated during operation */
+
+ crypto_put_session(ses_ptr);
+
+ kcop->task = current;
+ kcop->mm = current->mm;
+
+ if (cop->iv) {
+ rc = copy_from_user(kcop->iv, cop->iv, kcop->ivlen);
+ if (unlikely(rc)) {
+ derr(1, "error copying IV (%d bytes), copy_from_user returned %d for address %p",
+ kcop->ivlen, rc, cop->iv);
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+/* this function has to be called from process context */
+static int fill_cop_from_kcop(struct kernel_crypt_op *kcop, struct fcrypt *fcr)
+{
+ int ret;
+
+ if (kcop->digestsize) {
+ ret = copy_to_user(kcop->cop.mac,
+ kcop->hash_output, kcop->digestsize);
+ if (unlikely(ret))
+ return -EFAULT;
+ }
+ if (kcop->ivlen && kcop->cop.flags & COP_FLAG_WRITE_IV) {
+ ret = copy_to_user(kcop->cop.iv,
+ kcop->iv, kcop->ivlen);
+ if (unlikely(ret))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int kcop_from_user(struct kernel_crypt_op *kcop,
+ struct fcrypt *fcr, void __user *arg)
+{
+ if (unlikely(copy_from_user(&kcop->cop, arg, sizeof(kcop->cop))))
+ return -EFAULT;
+
+ return fill_kcop_from_cop(kcop, fcr);
+}
+
+static int kcop_to_user(struct kernel_crypt_op *kcop,
+ struct fcrypt *fcr, void __user *arg)
+{
+ int ret;
+
+ ret = fill_cop_from_kcop(kcop, fcr);
+ if (unlikely(ret)) {
+ derr(1, "Error in fill_cop_from_kcop");
+ return ret;
+ }
+
+ if (unlikely(copy_to_user(arg, &kcop->cop, sizeof(kcop->cop)))) {
+ derr(1, "Cannot copy to userspace");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static inline void tfm_info_to_alg_info(struct alg_info *dst, struct crypto_tfm *tfm)
+{
+ snprintf(dst->cra_name, CRYPTODEV_MAX_ALG_NAME,
+ "%s", crypto_tfm_alg_name(tfm));
+ snprintf(dst->cra_driver_name, CRYPTODEV_MAX_ALG_NAME,
+ "%s", crypto_tfm_alg_driver_name(tfm));
+}
+
+#ifndef CRYPTO_ALG_KERN_DRIVER_ONLY
+static unsigned int is_known_accelerated(struct crypto_tfm *tfm)
+{
+ const char *name = crypto_tfm_alg_driver_name(tfm);
+
+ if (name == NULL)
+ return 1; /* assume accelerated */
+
+ /* look for known crypto engine names */
+ if (strstr(name, "-talitos") ||
+ !strncmp(name, "mv-", 3) ||
+ !strncmp(name, "atmel-", 6) ||
+ strstr(name, "geode") ||
+ strstr(name, "hifn") ||
+ strstr(name, "-ixp4xx") ||
+ strstr(name, "-omap") ||
+ strstr(name, "-picoxcell") ||
+ strstr(name, "-s5p") ||
+ strstr(name, "-ppc4xx") ||
+ strstr(name, "-caam") ||
+ strstr(name, "-n2"))
+ return 1;
+
+ return 0;
+}
+#endif
+
+static int get_session_info(struct fcrypt *fcr, struct session_info_op *siop)
+{
+ struct csession *ses_ptr;
+ struct crypto_tfm *tfm;
+
+ /* this also enters ses_ptr->sem */
+ ses_ptr = crypto_get_session_by_sid(fcr, siop->ses);
+ if (unlikely(!ses_ptr)) {
+ derr(1, "invalid session ID=0x%08X", siop->ses);
+ return -EINVAL;
+ }
+
+ siop->flags = 0;
+
+ if (ses_ptr->cdata.init) {
+ if (ses_ptr->cdata.aead == 0)
+ tfm = cryptodev_crypto_blkcipher_tfm(ses_ptr->cdata.async.s);
+ else
+ tfm = crypto_aead_tfm(ses_ptr->cdata.async.as);
+ tfm_info_to_alg_info(&siop->cipher_info, tfm);
+#ifdef CRYPTO_ALG_KERN_DRIVER_ONLY
+ if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
+ siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
+#else
+ if (is_known_accelerated(tfm))
+ siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
+#endif
+ }
+ if (ses_ptr->hdata.init) {
+ tfm = crypto_ahash_tfm(ses_ptr->hdata.async.s);
+ tfm_info_to_alg_info(&siop->hash_info, tfm);
+#ifdef CRYPTO_ALG_KERN_DRIVER_ONLY
+ if (tfm->__crt_alg->cra_flags & CRYPTO_ALG_KERN_DRIVER_ONLY)
+ siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
+#else
+ if (is_known_accelerated(tfm))
+ siop->flags |= SIOP_FLAG_KERNEL_DRIVER_ONLY;
+#endif
+ }
+
+ siop->alignmask = ses_ptr->alignmask;
+
+ crypto_put_session(ses_ptr);
+ return 0;
+}
+
+static long
+cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_)
+{
+ void __user *arg = (void __user *)arg_;
+ int __user *p = arg;
+ struct session_op sop;
+ struct kernel_crypt_op kcop;
+ struct kernel_crypt_auth_op kcaop;
+ struct crypt_priv *pcr = filp->private_data;
+ struct fcrypt *fcr;
+ struct session_info_op siop;
+#ifdef CIOCCPHASH
+ struct cphash_op cphop;
+#endif
+ uint32_t ses;
+ int ret, fd;
+
+ if (unlikely(!pcr))
+ BUG();
+
+ fcr = &pcr->fcrypt;
+
+ switch (cmd) {
+ case CIOCASYMFEAT:
+ return put_user(0, p);
+ case CRIOGET:
+ fd = clonefd(filp);
+ ret = put_user(fd, p);
+ if (unlikely(ret)) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
+ sys_close(fd);
+#else
+ ksys_close(fd);
+#endif
+ return ret;
+ }
+ return ret;
+ case CIOCGSESSION:
+ if (unlikely(copy_from_user(&sop, arg, sizeof(sop))))
+ return -EFAULT;
+
+ ret = crypto_create_session(fcr, &sop);
+ if (unlikely(ret))
+ return ret;
+ ret = copy_to_user(arg, &sop, sizeof(sop));
+ if (unlikely(ret)) {
+ crypto_finish_session(fcr, sop.ses);
+ return -EFAULT;
+ }
+ return ret;
+ case CIOCFSESSION:
+ ret = get_user(ses, (uint32_t __user *)arg);
+ if (unlikely(ret))
+ return ret;
+ ret = crypto_finish_session(fcr, ses);
+ return ret;
+ case CIOCGSESSINFO:
+ if (unlikely(copy_from_user(&siop, arg, sizeof(siop))))
+ return -EFAULT;
+
+ ret = get_session_info(fcr, &siop);
+ if (unlikely(ret))
+ return ret;
+ return copy_to_user(arg, &siop, sizeof(siop));
+#ifdef CIOCCPHASH
+ case CIOCCPHASH:
+ if (unlikely(copy_from_user(&cphop, arg, sizeof(cphop))))
+ return -EFAULT;
+ return crypto_copy_hash_state(fcr, cphop.dst_ses, cphop.src_ses);
+#endif /* CIOCPHASH */
+ case CIOCCRYPT:
+ if (unlikely(ret = kcop_from_user(&kcop, fcr, arg))) {
+ dwarning(1, "Error copying from user");
+ return ret;
+ }
+
+ ret = crypto_run(fcr, &kcop);
+ if (unlikely(ret)) {
+ dwarning(1, "Error in crypto_run");
+ return ret;
+ }
+
+ return kcop_to_user(&kcop, fcr, arg);
+ case CIOCAUTHCRYPT:
+ if (unlikely(ret = kcaop_from_user(&kcaop, fcr, arg))) {
+ dwarning(1, "Error copying from user");
+ return ret;
+ }
+
+ ret = crypto_auth_run(fcr, &kcaop);
+ if (unlikely(ret)) {
+ dwarning(1, "Error in crypto_auth_run");
+ return ret;
+ }
+ return kcaop_to_user(&kcaop, fcr, arg);
+#ifdef ENABLE_ASYNC
+ case CIOCASYNCCRYPT:
+ if (unlikely(ret = kcop_from_user(&kcop, fcr, arg)))
+ return ret;
+
+ return crypto_async_run(pcr, &kcop);
+ case CIOCASYNCFETCH:
+ ret = crypto_async_fetch(pcr, &kcop);
+ if (unlikely(ret))
+ return ret;
+
+ return kcop_to_user(&kcop, fcr, arg);
+#endif
+ default:
+ return -EINVAL;
+ }
+}
+
+/* compatibility code for 32bit userlands */
+#ifdef CONFIG_COMPAT
+
+static inline void
+compat_to_session_op(struct compat_session_op *compat, struct session_op *sop)
+{
+ sop->cipher = compat->cipher;
+ sop->mac = compat->mac;
+ sop->keylen = compat->keylen;
+
+ sop->key = compat_ptr(compat->key);
+ sop->mackeylen = compat->mackeylen;
+ sop->mackey = compat_ptr(compat->mackey);
+ sop->ses = compat->ses;
+}
+
+static inline void
+session_op_to_compat(struct session_op *sop, struct compat_session_op *compat)
+{
+ compat->cipher = sop->cipher;
+ compat->mac = sop->mac;
+ compat->keylen = sop->keylen;
+
+ compat->key = ptr_to_compat(sop->key);
+ compat->mackeylen = sop->mackeylen;
+ compat->mackey = ptr_to_compat(sop->mackey);
+ compat->ses = sop->ses;
+}
+
+static inline void
+compat_to_crypt_op(struct compat_crypt_op *compat, struct crypt_op *cop)
+{
+ cop->ses = compat->ses;
+ cop->op = compat->op;
+ cop->flags = compat->flags;
+ cop->len = compat->len;
+
+ cop->src = compat_ptr(compat->src);
+ cop->dst = compat_ptr(compat->dst);
+ cop->mac = compat_ptr(compat->mac);
+ cop->iv = compat_ptr(compat->iv);
+}
+
+static inline void
+crypt_op_to_compat(struct crypt_op *cop, struct compat_crypt_op *compat)
+{
+ compat->ses = cop->ses;
+ compat->op = cop->op;
+ compat->flags = cop->flags;
+ compat->len = cop->len;
+
+ compat->src = ptr_to_compat(cop->src);
+ compat->dst = ptr_to_compat(cop->dst);
+ compat->mac = ptr_to_compat(cop->mac);
+ compat->iv = ptr_to_compat(cop->iv);
+}
+
+static int compat_kcop_from_user(struct kernel_crypt_op *kcop,
+ struct fcrypt *fcr, void __user *arg)
+{
+ struct compat_crypt_op compat_cop;
+
+ if (unlikely(copy_from_user(&compat_cop, arg, sizeof(compat_cop))))
+ return -EFAULT;
+ compat_to_crypt_op(&compat_cop, &kcop->cop);
+
+ return fill_kcop_from_cop(kcop, fcr);
+}
+
+static int compat_kcop_to_user(struct kernel_crypt_op *kcop,
+ struct fcrypt *fcr, void __user *arg)
+{
+ int ret;
+ struct compat_crypt_op compat_cop;
+
+ ret = fill_cop_from_kcop(kcop, fcr);
+ if (unlikely(ret)) {
+ dwarning(1, "Error in fill_cop_from_kcop");
+ return ret;
+ }
+ crypt_op_to_compat(&kcop->cop, &compat_cop);
+
+ if (unlikely(copy_to_user(arg, &compat_cop, sizeof(compat_cop)))) {
+ dwarning(1, "Error copying to user");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static long
+cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg_)
+{
+ void __user *arg = (void __user *)arg_;
+ struct crypt_priv *pcr = file->private_data;
+ struct fcrypt *fcr;
+ struct session_op sop;
+ struct compat_session_op compat_sop;
+ struct kernel_crypt_op kcop;
+ int ret;
+
+ if (unlikely(!pcr))
+ BUG();
+
+ fcr = &pcr->fcrypt;
+
+ switch (cmd) {
+ case CIOCASYMFEAT:
+ case CRIOGET:
+ case CIOCFSESSION:
+ case CIOCGSESSINFO:
+ return cryptodev_ioctl(file, cmd, arg_);
+
+ case COMPAT_CIOCGSESSION:
+ if (unlikely(copy_from_user(&compat_sop, arg,
+ sizeof(compat_sop))))
+ return -EFAULT;
+ compat_to_session_op(&compat_sop, &sop);
+
+ ret = crypto_create_session(fcr, &sop);
+ if (unlikely(ret))
+ return ret;
+
+ session_op_to_compat(&sop, &compat_sop);
+ ret = copy_to_user(arg, &compat_sop, sizeof(compat_sop));
+ if (unlikely(ret)) {
+ crypto_finish_session(fcr, sop.ses);
+ return -EFAULT;
+ }
+ return ret;
+
+ case COMPAT_CIOCCRYPT:
+ ret = compat_kcop_from_user(&kcop, fcr, arg);
+ if (unlikely(ret))
+ return ret;
+
+ ret = crypto_run(fcr, &kcop);
+ if (unlikely(ret))
+ return ret;
+
+ return compat_kcop_to_user(&kcop, fcr, arg);
+#ifdef ENABLE_ASYNC
+ case COMPAT_CIOCASYNCCRYPT:
+ if (unlikely(ret = compat_kcop_from_user(&kcop, fcr, arg)))
+ return ret;
+
+ return crypto_async_run(pcr, &kcop);
+ case COMPAT_CIOCASYNCFETCH:
+ ret = crypto_async_fetch(pcr, &kcop);
+ if (unlikely(ret))
+ return ret;
+
+ return compat_kcop_to_user(&kcop, fcr, arg);
+#endif
+ default:
+ return -EINVAL;
+ }
+}
+
+#endif /* CONFIG_COMPAT */
+
+static unsigned int cryptodev_poll(struct file *file, poll_table *wait)
+{
+ struct crypt_priv *pcr = file->private_data;
+ unsigned int ret = 0;
+
+ poll_wait(file, &pcr->user_waiter, wait);
+
+ if (!list_empty_careful(&pcr->done.list))
+ ret |= POLLIN | POLLRDNORM;
+ if (!list_empty_careful(&pcr->free.list) || pcr->itemcount < MAX_COP_RINGSIZE)
+ ret |= POLLOUT | POLLWRNORM;
+
+ return ret;
+}
+
+static const struct file_operations cryptodev_fops = {
+ .owner = THIS_MODULE,
+ .open = cryptodev_open,
+ .release = cryptodev_release,
+ .unlocked_ioctl = cryptodev_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = cryptodev_compat_ioctl,
+#endif /* CONFIG_COMPAT */
+ .poll = cryptodev_poll,
+};
+
+static struct miscdevice cryptodev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "crypto",
+ .fops = &cryptodev_fops,
+ .mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH,
+};
+
+static int __init
+cryptodev_register(void)
+{
+ int rc;
+
+ rc = misc_register(&cryptodev);
+ if (unlikely(rc)) {
+ pr_err(PFX "registration of /dev/crypto failed\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit
+cryptodev_deregister(void)
+{
+ misc_deregister(&cryptodev);
+}
+
+/* ====== Module init/exit ====== */
+static struct ctl_table verbosity_ctl_dir[] = {
+ {
+ .procname = "cryptodev_verbosity",
+ .data = &cryptodev_verbosity,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {},
+};
+
+static struct ctl_table verbosity_ctl_root[] = {
+ {
+ .procname = "ioctl",
+ .mode = 0555,
+ .child = verbosity_ctl_dir,
+ },
+ {},
+};
+static struct ctl_table_header *verbosity_sysctl_header;
+static int __init init_cryptodev(void)
+{
+ int rc;
+
+ cryptodev_wq = create_workqueue("cryptodev_queue");
+ if (unlikely(!cryptodev_wq)) {
+ pr_err(PFX "failed to allocate the cryptodev workqueue\n");
+ return -EFAULT;
+ }
+
+ rc = cryptodev_register();
+ if (unlikely(rc)) {
+ destroy_workqueue(cryptodev_wq);
+ return rc;
+ }
+
+ verbosity_sysctl_header = register_sysctl_table(verbosity_ctl_root);
+
+ pr_info(PFX "driver %s loaded.\n", VERSION);
+
+ return 0;
+}
+
+static void __exit exit_cryptodev(void)
+{
+ flush_workqueue(cryptodev_wq);
+ destroy_workqueue(cryptodev_wq);
+
+ if (verbosity_sysctl_header)
+ unregister_sysctl_table(verbosity_sysctl_header);
+
+ cryptodev_deregister();
+ pr_info(PFX "driver unloaded.\n");
+}
+
+module_init(init_cryptodev);
+module_exit(exit_cryptodev);
+
diff --git a/drivers/cryptodev-linux-master/lib/Makefile b/drivers/cryptodev-linux-master/lib/Makefile
new file mode 100644
index 00000000..3bedc341
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/Makefile
@@ -0,0 +1,15 @@
+CFLAGS=-g -O2 -Wall
+
+all: benchmark
+
+benchmark: main.c libthreshold.a
+ gcc $(CFLAGS) -DDEBUG -o $@ $^ -lssl -lcrypto libthreshold.a
+
+.o:
+ gcc $(CCFLAGS) -c $< -o $@
+
+libthreshold.a: benchmark.o hash.o threshold.o combo.o
+ ar rcs $@ $^
+
+clean:
+ rm -f *.o *~ benchmark libthreshold.a
diff --git a/drivers/cryptodev-linux-master/lib/benchmark.c b/drivers/cryptodev-linux-master/lib/benchmark.c
new file mode 100644
index 00000000..a04efbc4
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/benchmark.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include "benchmark.h"
+
+int benchmark_must_finish = 0;
+
+static void
+alarm_handler (int signo)
+{
+ benchmark_must_finish = 1;
+}
+
+int start_benchmark(struct benchmark_st * st)
+{
+ int ret;
+ struct itimerval timer;
+
+ memset(st, 0, sizeof(*st));
+
+ st->old_handler = signal (SIGPROF, alarm_handler);
+
+ ret = gettimeofday (&st->start, NULL);
+ if (ret < 0) {
+ perror("gettimeofday");
+ return -1;
+ }
+
+ benchmark_must_finish = 0;
+
+ memset(&timer, 0, sizeof(timer));
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = 100*1000;
+
+ ret = setitimer(ITIMER_PROF, &timer, NULL);
+ if (ret < 0) {
+ perror("setitimer");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Returns -1 on error or 0 on success.
+ * elapsed: the elapsed time in milliseconds
+ */
+int stop_benchmark(struct benchmark_st * st, unsigned long * elapsed)
+{
+ unsigned long msecs;
+ struct timeval stop;
+ int ret;
+
+ signal(SIGPROF, st->old_handler);
+
+ ret = gettimeofday (&stop, NULL);
+ if (ret < 0)
+ return -1;
+
+ msecs = (stop.tv_sec * 1000 + stop.tv_usec / 1000 -
+ (st->start.tv_sec * 1000 + st->start.tv_usec / (1000)));
+
+ if (elapsed) *elapsed = msecs;
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/lib/benchmark.h b/drivers/cryptodev-linux-master/lib/benchmark.h
new file mode 100644
index 00000000..173552ec
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/benchmark.h
@@ -0,0 +1,18 @@
+#include <sys/time.h>
+#include <time.h>
+#include <sys/time.h>
+#include <signal.h>
+
+typedef void (*sighandler_t)(int);
+
+struct benchmark_st
+{
+ struct timeval start;
+ sighandler_t old_handler;
+};
+
+extern int benchmark_must_finish;
+
+int start_benchmark(struct benchmark_st * st);
+int stop_benchmark(struct benchmark_st * st, unsigned long * elapsed);
+
diff --git a/drivers/cryptodev-linux-master/lib/combo.c b/drivers/cryptodev-linux-master/lib/combo.c
new file mode 100644
index 00000000..b26da0a5
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/combo.c
@@ -0,0 +1,171 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "benchmark.h"
+#include "hash.h"
+
+int aead_ctx_init(struct cryptodev_ctx* ctx, int cipher, int hash, void* key, int key_size, int cfd)
+{
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->cfd = cfd;
+
+ ctx->sess.mac = hash;
+ ctx->sess.cipher = cipher;
+ ctx->sess.key = key;
+ ctx->sess.keylen = key_size;
+
+ if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return -1;
+ }
+
+#ifdef CIOCGSESSINFO
+ memset(&siop, 0, sizeof(siop));
+ siop.ses = ctx->sess.ses;
+ if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return -1;
+ }
+#ifdef DEBUG
+ printf("Got %s-%s with drivers %s and %s\n",
+ siop.cipher_info.cra_name, siop.hash_info.cra_name,
+ siop.cipher_info.cra_driver_name, siop.hash_info.cra_driver_name);
+#endif
+ /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask);*/
+ ctx->alignmask = siop.alignmask;
+#endif
+ return 0;
+}
+
+void aead_ctx_deinit(struct cryptodev_ctx* ctx)
+{
+ if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+}
+
+int
+aead_encrypt(struct cryptodev_ctx* ctx, const void* iv, const void* plaintext, void* ciphertext, size_t size, void* digest)
+{
+ struct crypt_auth_op cryp;
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.len = size;
+ cryp.iv = (void*)iv;
+ cryp.iv_len = 16;
+ cryp.src = (void*)plaintext;
+ cryp.dst = (void*)ciphertext;
+ cryp.flags = COP_FLAG_AEAD_TLS_TYPE;
+
+ if (ioctl(ctx->cfd, CIOCAUTHCRYPT, &cryp)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+static const int sizes[] = {64, 256, 512, 1024, 4096, 16*1024};
+
+
+int aead_test(int cipher, int mac, void* ukey, int ukey_size,
+ void* user_ctx, void (*user_combo)(void* user_ctx, void* plaintext, void* ciphertext, int size, void* res))
+{
+ int cfd = -1, i, ret;
+ struct cryptodev_ctx ctx;
+ uint8_t digest[AALG_MAX_RESULT_LEN];
+ char text[16*1024];
+ char ctext[16*1024];
+ char iv[16];
+ unsigned long elapsed, counted;
+ double t1, t2;
+ struct benchmark_st bst;
+
+ /* Open the crypto device */
+ cfd = open("/dev/crypto", O_RDWR, 0);
+ if (cfd < 0) {
+ perror("open(/dev/crypto)");
+ return -1;
+ }
+
+ aead_ctx_init(&ctx, cipher, mac, ukey, ukey_size, cfd);
+
+ for (i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
+ counted = 0;
+ ret = start_benchmark(&bst);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+
+ do {
+ if (aead_encrypt(&ctx, iv, text, text, sizes[i], digest) < 0)
+ return -2;
+ counted += sizes[i];
+ } while(benchmark_must_finish==0);
+
+ ret = stop_benchmark(&bst, &elapsed);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+
+ t1 = (double)counted/(double)elapsed;
+
+ /* now check the user function */
+ counted = 0;
+ ret = start_benchmark(&bst);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+
+ do {
+ user_combo(user_ctx, text, ctext, sizes[i], digest);
+ counted += sizes[i];
+ } while(benchmark_must_finish==0);
+
+ ret = stop_benchmark(&bst, &elapsed);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+
+ t2 = (double)counted/(double)elapsed;
+
+#ifdef DEBUG
+ printf("%d: kernel: %.4f bytes/msec, user: %.4f bytes/msec\n", sizes[i], t1, t2);
+#endif
+ if (t1 > t2) {
+ ret = sizes[i];
+ goto finish;
+ }
+ }
+
+ ret = -1;
+finish:
+ aead_ctx_deinit(&ctx);
+
+ /* Close the original descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+ return ret;
+}
diff --git a/drivers/cryptodev-linux-master/lib/hash.c b/drivers/cryptodev-linux-master/lib/hash.c
new file mode 100644
index 00000000..386fd7e8
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/hash.c
@@ -0,0 +1,161 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "hash.h"
+#include "benchmark.h"
+
+int hash_ctx_init(struct cryptodev_ctx* ctx, int hash, int cfd)
+{
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->cfd = cfd;
+
+ ctx->sess.mac = hash;
+
+ if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return -1;
+ }
+
+#ifdef CIOCGSESSINFO
+ memset(&siop, 0, sizeof(siop));
+ siop.ses = ctx->sess.ses;
+ if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return -1;
+ }
+#ifdef DEBUG
+ printf("Got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+#endif
+ /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask);*/
+ ctx->alignmask = siop.alignmask;
+#endif
+ return 0;
+}
+
+void hash_ctx_deinit(struct cryptodev_ctx* ctx)
+{
+ if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+}
+
+int
+hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest)
+{
+ struct crypt_op cryp;
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = ctx->sess.ses;
+ cryp.len = size;
+ cryp.src = (void*)text;
+ cryp.mac = digest;
+ if (ioctl(ctx->cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return -1;
+ }
+
+ return 0;
+}
+
+static const int sizes[] = {64, 256, 512, 1024, 4096, 16*1024};
+
+/* Worst case running time: around 1.2 secs
+ */
+int hash_test(int algo, void (*user_hash)(void* text, int size, void* res))
+{
+ int cfd = -1, i, ret;
+ struct cryptodev_ctx ctx;
+ uint8_t digest[AALG_MAX_RESULT_LEN];
+ char text[16*1024];
+ unsigned long elapsed, counted;
+ double t1, t2;
+ struct benchmark_st bst;
+
+ /* Open the crypto device */
+ cfd = open("/dev/crypto", O_RDWR, 0);
+ if (cfd < 0) {
+ perror("open(/dev/crypto)");
+ return -1;
+ }
+
+ hash_ctx_init(&ctx, algo, cfd);
+
+ for (i=0;i<sizeof(sizes)/sizeof(sizes[0]);i++) {
+ counted = 0;
+ ret = start_benchmark(&bst);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+
+ do {
+ hash(&ctx, text, sizes[i], digest);
+ counted += sizes[i];
+ } while(benchmark_must_finish==0);
+
+ ret = stop_benchmark(&bst, &elapsed);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+ t1 = (double)counted/(double)elapsed;
+
+ /* now check the user function */
+ counted = 0;
+ ret = start_benchmark(&bst);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+
+
+ do {
+ user_hash(text, sizes[i], digest);
+ counted += sizes[i];
+ } while(benchmark_must_finish==0);
+
+ ret = stop_benchmark(&bst, &elapsed);
+ if (ret < 0) {
+ ret = -1;
+ goto finish;
+ }
+
+ t2 = (double)counted/(double)elapsed;
+
+ if (t1 > t2) {
+ ret = sizes[i];
+ goto finish;
+ }
+#ifdef DEBUG
+ printf("%d: kernel: %.4f bytes/msec, user: %.4f bytes/msec\n", sizes[i], t1, t2);
+#endif
+ }
+
+ ret = -1;
+finish:
+ hash_ctx_deinit(&ctx);
+
+ /* Close the original descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+ return ret;
+}
+
diff --git a/drivers/cryptodev-linux-master/lib/hash.h b/drivers/cryptodev-linux-master/lib/hash.h
new file mode 100644
index 00000000..7c32ceaa
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/hash.h
@@ -0,0 +1,20 @@
+#ifndef HASH_H
+# define HASH_H
+
+#include <stdint.h>
+
+struct cryptodev_ctx {
+ int cfd;
+ struct session_op sess;
+ uint16_t alignmask;
+};
+
+int hash_ctx_init(struct cryptodev_ctx* ctx, int hash, int cfd);
+void hash_ctx_deinit(struct cryptodev_ctx* ctx);
+int hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest);
+int hash_test(int algo, void (*user_hash)(void* text, int size, void* res));
+
+int aead_test(int cipher, int mac, void* ukey, int ukey_size,
+ void* user_ctx, void (*user_combo)(void* user_ctx, void* plaintext, void* ciphertext, int size, void* res));
+
+#endif
diff --git a/drivers/cryptodev-linux-master/lib/main.c b/drivers/cryptodev-linux-master/lib/main.c
new file mode 100644
index 00000000..443779af
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/main.c
@@ -0,0 +1,28 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "threshold.h"
+
+int main()
+{
+int ret;
+
+ ret = get_sha1_threshold();
+ if (ret > 0)
+ printf("SHA1 in kernel outperforms user-space after %d input bytes\n", ret);
+
+ ret = get_aes_sha1_threshold();
+ if (ret > 0)
+ printf("AES-SHA1 in kernel outperforms user-space after %d input bytes\n", ret);
+
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/lib/threshold.c b/drivers/cryptodev-linux-master/lib/threshold.c
new file mode 100644
index 00000000..b002d58e
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/threshold.c
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include <openssl/aes.h>
+#include <openssl/engine.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include "hash.h"
+#include "threshold.h"
+
+void sha_hash(void* text, int size, void* digest)
+{
+SHA_CTX ctx;
+
+ SHA_Init(&ctx);
+
+ SHA_Update(&ctx, text, size);
+
+ SHA_Final(digest, &ctx);
+}
+
+void aes_sha_combo(void* ctx, void* plaintext, void* ciphertext, int size, void* tag)
+{
+uint8_t iv[16];
+AES_KEY* key = ctx;
+HMAC_CTX hctx;
+unsigned int rlen = 20;
+
+ HMAC_CTX_init(&hctx);
+ HMAC_Init_ex(&hctx, iv, 16, EVP_sha1(), NULL);
+
+ HMAC_Update(&hctx, plaintext, size);
+
+ HMAC_Final(&hctx, tag, &rlen);
+ HMAC_CTX_cleanup(&hctx);
+
+ AES_cbc_encrypt(plaintext, ciphertext, size, key, iv, 1);
+}
+
+int get_sha1_threshold()
+{
+ return hash_test(CRYPTO_SHA1, sha_hash);
+}
+
+int get_aes_sha1_threshold()
+{
+AES_KEY key;
+uint8_t ukey[16];
+
+ ENGINE_load_builtin_engines();
+ ENGINE_register_all_complete();
+
+ memset(ukey, 0xaf, sizeof(ukey));
+ AES_set_encrypt_key(ukey, 16*8, &key);
+
+ return aead_test(CRYPTO_AES_CBC, CRYPTO_SHA1, ukey, 16, &key, aes_sha_combo);
+}
+
diff --git a/drivers/cryptodev-linux-master/lib/threshold.h b/drivers/cryptodev-linux-master/lib/threshold.h
new file mode 100644
index 00000000..6c11019b
--- /dev/null
+++ b/drivers/cryptodev-linux-master/lib/threshold.h
@@ -0,0 +1,10 @@
+/* Return the number of bytes after which the
+ * kernel operation is more efficient to use.
+ * If return value is -1, then kernel operation
+ * cannot, or shouldn't be used, because it is always
+ * slower.
+ *
+ * Running time ~= 1.2 seconds per call.
+ */
+int get_sha1_threshold();
+int get_aes_sha1_threshold();
diff --git a/drivers/cryptodev-linux-master/main.c b/drivers/cryptodev-linux-master/main.c
new file mode 100644
index 00000000..b2ef5f7e
--- /dev/null
+++ b/drivers/cryptodev-linux-master/main.c
@@ -0,0 +1,269 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2004 Michal Ludvig <mludvig@logix.net.nz>, SuSE Labs
+ * Copyright (c) 2009-2013 Nikos Mavrogiannopoulos <nmav@gnutls.org>
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Device /dev/crypto provides an interface for
+ * accessing kernel CryptoAPI algorithms (ciphers,
+ * hashes) from userspace programs.
+ *
+ * /dev/crypto interface was originally introduced in
+ * OpenBSD and this module attempts to keep the API.
+ *
+ */
+#include <crypto/hash.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/ioctl.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+#include <linux/pagemap.h>
+#include <linux/poll.h>
+#include <linux/uaccess.h>
+#include <crypto/cryptodev.h>
+#include <crypto/scatterwalk.h>
+#include <linux/scatterlist.h>
+#include "cryptodev_int.h"
+#include "zc.h"
+#include "cryptlib.h"
+#include "version.h"
+
+/* This file contains the traditional operations of encryption
+ * and hashing of /dev/crypto.
+ */
+
+static int
+hash_n_crypt(struct csession *ses_ptr, struct crypt_op *cop,
+ struct scatterlist *src_sg, struct scatterlist *dst_sg,
+ uint32_t len)
+{
+ int ret;
+
+ /* Always hash before encryption and after decryption. Maybe
+ * we should introduce a flag to switch... TBD later on.
+ */
+ if (cop->op == COP_ENCRYPT) {
+ if (ses_ptr->hdata.init != 0) {
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ src_sg, len);
+ if (unlikely(ret))
+ goto out_err;
+ }
+ if (ses_ptr->cdata.init != 0) {
+ ret = cryptodev_cipher_encrypt(&ses_ptr->cdata,
+ src_sg, dst_sg, len);
+
+ if (unlikely(ret))
+ goto out_err;
+ }
+ } else {
+ if (ses_ptr->cdata.init != 0) {
+ ret = cryptodev_cipher_decrypt(&ses_ptr->cdata,
+ src_sg, dst_sg, len);
+
+ if (unlikely(ret))
+ goto out_err;
+ }
+
+ if (ses_ptr->hdata.init != 0) {
+ ret = cryptodev_hash_update(&ses_ptr->hdata,
+ dst_sg, len);
+ if (unlikely(ret))
+ goto out_err;
+ }
+ }
+ return 0;
+out_err:
+ derr(0, "CryptoAPI failure: %d", ret);
+ return ret;
+}
+
+/* This is the main crypto function - feed it with plaintext
+ and get a ciphertext (or vice versa :-) */
+static int
+__crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop)
+{
+ char *data;
+ char __user *src, *dst;
+ struct scatterlist sg;
+ size_t nbytes, bufsize;
+ int ret = 0;
+
+ nbytes = cop->len;
+ data = (char *)__get_free_page(GFP_KERNEL);
+
+ if (unlikely(!data)) {
+ derr(1, "Error getting free page.");
+ return -ENOMEM;
+ }
+
+ bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes;
+
+ src = cop->src;
+ dst = cop->dst;
+
+ while (nbytes > 0) {
+ size_t current_len = nbytes > bufsize ? bufsize : nbytes;
+
+ if (unlikely(copy_from_user(data, src, current_len))) {
+ derr(1, "Error copying %zu bytes from user address %p.", current_len, src);
+ ret = -EFAULT;
+ break;
+ }
+
+ sg_init_one(&sg, data, current_len);
+
+ ret = hash_n_crypt(ses_ptr, cop, &sg, &sg, current_len);
+
+ if (unlikely(ret)) {
+ derr(1, "hash_n_crypt failed.");
+ break;
+ }
+
+ if (ses_ptr->cdata.init != 0) {
+ if (unlikely(copy_to_user(dst, data, current_len))) {
+ derr(1, "could not copy to user.");
+ ret = -EFAULT;
+ break;
+ }
+ }
+
+ dst += current_len;
+ nbytes -= current_len;
+ src += current_len;
+ }
+
+ free_page((unsigned long)data);
+ return ret;
+}
+
+
+
+/* This is the main crypto function - zero-copy edition */
+static int
+__crypto_run_zc(struct csession *ses_ptr, struct kernel_crypt_op *kcop)
+{
+ struct scatterlist *src_sg, *dst_sg;
+ struct crypt_op *cop = &kcop->cop;
+ int ret = 0;
+
+ ret = get_userbuf(ses_ptr, cop->src, cop->len, cop->dst, cop->len,
+ kcop->task, kcop->mm, &src_sg, &dst_sg);
+ if (unlikely(ret)) {
+ derr(1, "Error getting user pages. Falling back to non zero copy.");
+ return __crypto_run_std(ses_ptr, cop);
+ }
+
+ ret = hash_n_crypt(ses_ptr, cop, src_sg, dst_sg, cop->len);
+
+ release_user_pages(ses_ptr);
+ return ret;
+}
+
+int crypto_run(struct fcrypt *fcr, struct kernel_crypt_op *kcop)
+{
+ struct csession *ses_ptr;
+ struct crypt_op *cop = &kcop->cop;
+ int ret = 0;
+
+ if (unlikely(cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) {
+ ddebug(1, "invalid operation op=%u", cop->op);
+ return -EINVAL;
+ }
+
+ /* this also enters ses_ptr->sem */
+ ses_ptr = crypto_get_session_by_sid(fcr, cop->ses);
+ if (unlikely(!ses_ptr)) {
+ derr(1, "invalid session ID=0x%08X", cop->ses);
+ return -EINVAL;
+ }
+
+ if (ses_ptr->hdata.init != 0 && (cop->flags == 0 || cop->flags & COP_FLAG_RESET)) {
+ ret = cryptodev_hash_reset(&ses_ptr->hdata);
+ if (unlikely(ret)) {
+ derr(1, "error in cryptodev_hash_reset()");
+ goto out_unlock;
+ }
+ }
+
+ if (ses_ptr->cdata.init != 0) {
+ int blocksize = ses_ptr->cdata.blocksize;
+
+ if (unlikely(cop->len % blocksize)) {
+ derr(1, "data size (%u) isn't a multiple of block size (%u)",
+ cop->len, blocksize);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ cryptodev_cipher_set_iv(&ses_ptr->cdata, kcop->iv,
+ min(ses_ptr->cdata.ivsize, kcop->ivlen));
+ }
+
+ if (likely(cop->len)) {
+ if(!(cop->flags & COP_FLAG_ZC)){
+ if (!(cop->flags & COP_FLAG_NO_ZC)) {
+ if (unlikely(ses_ptr->alignmask && !IS_ALIGNED((unsigned long)cop->src, ses_ptr->alignmask + 1))) {
+ dwarning(2, "source address %p is not %d byte aligned - disabling zero copy",
+ cop->src, ses_ptr->alignmask + 1);
+ cop->flags |= COP_FLAG_NO_ZC;
+ }
+
+ if (unlikely(ses_ptr->alignmask && !IS_ALIGNED((unsigned long)cop->dst, ses_ptr->alignmask + 1))) {
+ dwarning(2, "destination address %p is not %d byte aligned - disabling zero copy",
+ cop->dst, ses_ptr->alignmask + 1);
+ cop->flags |= COP_FLAG_NO_ZC;
+ }
+ }
+ }
+
+ if (cop->flags & COP_FLAG_NO_ZC)
+ ret = __crypto_run_std(ses_ptr, &kcop->cop);
+ else
+ ret = __crypto_run_zc(ses_ptr, kcop);
+ if (unlikely(ret))
+ goto out_unlock;
+ }
+
+ if (ses_ptr->cdata.init != 0) {
+ cryptodev_cipher_get_iv(&ses_ptr->cdata, kcop->iv,
+ min(ses_ptr->cdata.ivsize, kcop->ivlen));
+ }
+
+ if (ses_ptr->hdata.init != 0 &&
+ ((cop->flags & COP_FLAG_FINAL) ||
+ (!(cop->flags & COP_FLAG_UPDATE) || cop->len == 0))) {
+
+ ret = cryptodev_hash_final(&ses_ptr->hdata, kcop->hash_output);
+ if (unlikely(ret)) {
+ derr(0, "CryptoAPI failure: %d", ret);
+ goto out_unlock;
+ }
+ kcop->digestsize = ses_ptr->hdata.digestsize;
+ }
+
+out_unlock:
+ crypto_put_session(ses_ptr);
+ return ret;
+}
diff --git a/drivers/cryptodev-linux-master/tests/Makefile b/drivers/cryptodev-linux-master/tests/Makefile
new file mode 100644
index 00000000..2502f32b
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/Makefile
@@ -0,0 +1,47 @@
+CFLAGS += -I.. $(CRYPTODEV_CFLAGS) -Wall -Werror
+
+comp_progs := cipher_comp hash_comp hmac_comp
+
+hostprogs := cipher cipher-aead hmac speed async_cipher async_hmac \
+ async_speed sha_speed hashcrypt_speed fullspeed cipher-gcm \
+ cipher-aead-srtp $(comp_progs)
+
+example-cipher-objs := cipher.o
+example-cipher-aead-objs := cipher-aead.o
+example-hmac-objs := hmac.o
+example-speed-objs := speed.c
+example-fullspeed-objs := fullspeed.c
+example-sha-speed-objs := sha_speed.c
+example-async-cipher-objs := async_cipher.o
+example-async-hmac-objs := async_hmac.o
+example-async-speed-objs := async_speed.o
+example-hashcrypt-speed-objs := hashcrypt_speed.c
+
+prefix ?= /usr/local
+execprefix ?= $(prefix)
+bindir = $(execprefix)/bin
+
+all: $(hostprogs)
+
+check: $(hostprogs)
+ ./cipher
+ ./hmac
+ ./async_cipher
+ ./async_hmac
+ ./cipher-aead-srtp
+ ./cipher-gcm
+ ./cipher-aead
+
+install:
+ install -d $(DESTDIR)/$(bindir)
+ for prog in $(hostprogs); do \
+ install -m 755 $$prog $(DESTDIR)/$(bindir); \
+ done
+
+clean:
+ rm -f *.o *~ $(hostprogs)
+
+${comp_progs}: LDLIBS += -lssl -lcrypto
+${comp_progs}: %: %.o openssl_wrapper.o
+
+.PHONY: all clean check install
diff --git a/drivers/cryptodev-linux-master/tests/async_cipher.c b/drivers/cryptodev-linux-master/tests/async_cipher.c
new file mode 100644
index 00000000..7a184e5a
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/async_cipher.c
@@ -0,0 +1,339 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "asynchelper.h"
+#include "testhelper.h"
+
+#ifdef ENABLE_ASYNC
+
+static int debug = 0;
+
+#define DATA_SIZE 8*1024
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+
+static int
+test_crypto(int cfd)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ struct crypt_op cryp;
+
+ if (debug) printf("running %s\n", __func__);
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ memset(key, 0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ if (debug) printf("%s: got the session\n", __func__);
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+#else
+ plaintext = plaintext_raw;
+ ciphertext = ciphertext_raw;
+#endif
+ memset(plaintext, 0x15, DATA_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = DATA_SIZE;
+ cryp.src = plaintext;
+ cryp.dst = ciphertext;
+ cryp.iv = iv;
+ cryp.op = COP_ENCRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ if (debug) printf("%s: data encrypted\n", __func__);
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+ if (debug) printf("%s: session finished\n", __func__);
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+ if (debug) printf("%s: got new session\n", __func__);
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cryp.ses = sess.ses;
+ cryp.len = DATA_SIZE;
+ cryp.src = ciphertext;
+ cryp.dst = ciphertext;
+ cryp.iv = iv;
+ cryp.op = COP_DECRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ if (debug) printf("%s: data encrypted\n", __func__);
+
+ /* Verify the result */
+ if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ return 1;
+ } else if (debug)
+ printf("Test passed\n");
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int test_aes(int cfd)
+{
+ uint8_t plaintext1_raw[BLOCK_SIZE + 63], *plaintext1;
+ uint8_t ciphertext1[BLOCK_SIZE] = { 0xdf, 0x55, 0x6a, 0x33, 0x43, 0x8d, 0xb8, 0x7b, 0xc4, 0x1b, 0x17, 0x52, 0xc5, 0x5e, 0x5e, 0x49 };
+ uint8_t iv1[BLOCK_SIZE];
+ uint8_t key1[KEY_SIZE] = { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ uint8_t plaintext2_data[BLOCK_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 };
+ uint8_t plaintext2_raw[BLOCK_SIZE + 63], *plaintext2;
+ uint8_t ciphertext2[BLOCK_SIZE] = { 0xb7, 0x97, 0x2b, 0x39, 0x41, 0xc4, 0x4b, 0x90, 0xaf, 0xa7, 0xb2, 0x64, 0xbf, 0xba, 0x73, 0x87 };
+ uint8_t iv2[BLOCK_SIZE];
+ uint8_t key2[KEY_SIZE];
+
+ struct session_op sess1, sess2;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop1, siop2;
+#endif
+ struct crypt_op cryp1, cryp2;
+
+ memset(&sess1, 0, sizeof(sess1));
+ memset(&sess2, 0, sizeof(sess2));
+ memset(&cryp1, 0, sizeof(cryp1));
+ memset(&cryp2, 0, sizeof(cryp2));
+
+ /* Get crypto session for AES128 */
+ sess1.cipher = CRYPTO_AES_CBC;
+ sess1.keylen = KEY_SIZE;
+ sess1.key = key1;
+ if (ioctl(cfd, CIOCGSESSION, &sess1)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop1.ses = sess1.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop1)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ plaintext1 = buf_align(plaintext1_raw, siop1.alignmask);
+#else
+ plaintext1 = plaintext1_raw;
+#endif
+ memset(plaintext1, 0x0, BLOCK_SIZE);
+
+ memset(iv1, 0x0, sizeof(iv1));
+ memset(key2, 0x0, sizeof(key2));
+
+ /* Get second crypto session for AES128 */
+ sess2.cipher = CRYPTO_AES_CBC;
+ sess2.keylen = KEY_SIZE;
+ sess2.key = key2;
+ if (ioctl(cfd, CIOCGSESSION, &sess2)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop2.ses = sess2.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop2)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ plaintext2 = buf_align(plaintext2_raw, siop2.alignmask);
+#else
+ plaintext2 = plaintext2_raw;
+#endif
+ memcpy(plaintext2, plaintext2_data, BLOCK_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cryp1.ses = sess1.ses;
+ cryp1.len = BLOCK_SIZE;
+ cryp1.src = plaintext1;
+ cryp1.dst = plaintext1;
+ cryp1.iv = iv1;
+ cryp1.op = COP_ENCRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp1), 0);
+ if (debug) printf("cryp1 written out\n");
+
+ memset(iv2, 0x0, sizeof(iv2));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp2.ses = sess2.ses;
+ cryp2.len = BLOCK_SIZE;
+ cryp2.src = plaintext2;
+ cryp2.dst = plaintext2;
+ cryp2.iv = iv2;
+ cryp2.op = COP_ENCRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp2), 0);
+ if (debug) printf("cryp2 written out\n");
+
+ DO_OR_DIE(do_async_fetch(cfd, &cryp1), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp2), 0);
+ if (debug) printf("cryp1 + cryp2 successfully read\n");
+
+ /* Verify the result */
+ if (memcmp(plaintext1, ciphertext1, BLOCK_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < BLOCK_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", plaintext1[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < BLOCK_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", ciphertext1[i]);
+ }
+ printf("\n");
+ return 1;
+ } else {
+ if (debug) printf("result 1 passed\n");
+ }
+
+ /* Test 2 */
+
+ /* Verify the result */
+ if (memcmp(plaintext2, ciphertext2, BLOCK_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < BLOCK_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", plaintext2[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < BLOCK_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", ciphertext2[i]);
+ }
+ printf("\n");
+ return 1;
+ } else {
+ if (debug) printf("result 2 passed\n");
+ }
+
+ if (debug) printf("AES Test passed\n");
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess1.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+ if (ioctl(cfd, CIOCFSESSION, &sess2.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+ int fd = -1, cfd = -1;
+
+ if (argc > 1) debug = 1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Clone file descriptor */
+ if (ioctl(fd, CRIOGET, &cfd)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+ if (test_aes(cfd))
+ return 1;
+
+ if (test_crypto(cfd))
+ return 1;
+
+ /* Close cloned descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
+#else
+int
+main(int argc, char** argv)
+{
+ return (0);
+}
+#endif
diff --git a/drivers/cryptodev-linux-master/tests/async_hmac.c b/drivers/cryptodev-linux-master/tests/async_hmac.c
new file mode 100644
index 00000000..014b8ed7
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/async_hmac.c
@@ -0,0 +1,301 @@
+/*
+ * Demo on how to use /dev/crypto device for HMAC.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "asynchelper.h"
+
+#ifdef ENABLE_ASYNC
+
+static int debug = 0;
+
+#define DATA_SIZE 4096
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+#define SHA1_HASH_LEN 20
+
+static int
+test_crypto(int cfd)
+{
+ struct {
+ uint8_t in[DATA_SIZE],
+ encrypted[DATA_SIZE],
+ decrypted[DATA_SIZE],
+ iv[BLOCK_SIZE],
+ key[KEY_SIZE];
+ } data;
+ struct session_op sess;
+ struct crypt_op cryp;
+ uint8_t mac[AALG_MAX_RESULT_LEN];
+ uint8_t oldmac[AALG_MAX_RESULT_LEN];
+ uint8_t md5_hmac_out[] = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38";
+ uint8_t sha1_out[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
+ int i;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Use the garbage that is on the stack :-) */
+ /* memset(&data, 0, sizeof(data)); */
+
+ /* SHA1 plain test */
+ memset(mac, 0, sizeof(mac));
+
+ sess.cipher = 0;
+ sess.mac = CRYPTO_SHA1;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof("what do ya want for nothing?")-1;
+ cryp.src = (uint8_t *)"what do ya want for nothing?";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ if (memcmp(mac, sha1_out, 20)!=0) {
+ printf("mac: ");
+ for (i=0;i<SHA1_HASH_LEN;i++) {
+ printf("%.2x", (uint8_t)mac[i]);
+ }
+ puts("\n");
+ fprintf(stderr, "HASH test 1: failed\n");
+ } else {
+ if (debug) fprintf(stderr, "HASH test 1: passed\n");
+ }
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* MD5-HMAC test */
+ memset(mac, 0, sizeof(mac));
+
+ sess.cipher = 0;
+ sess.mackey = (uint8_t *)"Jefe";
+ sess.mackeylen = 4;
+ sess.mac = CRYPTO_MD5_HMAC;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof("what do ya want for nothing?")-1;
+ cryp.src = (uint8_t *)"what do ya want for nothing?";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ if (memcmp(mac, md5_hmac_out, 16)!=0) {
+ printf("mac: ");
+ for (i=0;i<SHA1_HASH_LEN;i++) {
+ printf("%.2x", (uint8_t)mac[i]);
+ }
+ puts("\n");
+ fprintf(stderr, "HMAC test 1: failed\n");
+ } else {
+ if (debug) fprintf(stderr, "HMAC test 1: passed\n");
+ }
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Hash and encryption in one step test */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.keylen = KEY_SIZE;
+ sess.key = data.key;
+ sess.mackeylen = 16;
+ sess.mackey = (uint8_t *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = sizeof(data.in);
+ cryp.src = data.in;
+ cryp.dst = data.encrypted;
+ cryp.iv = data.iv;
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ memcpy(oldmac, mac, sizeof(mac));
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cryp.src = data.encrypted;
+ cryp.dst = data.decrypted;
+ cryp.op = COP_DECRYPT;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ /* Verify the result */
+ if (memcmp(data.in, data.decrypted, sizeof(data.in)) != 0) {
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ return 1;
+ } else if (debug)
+ printf("Crypt Test: passed\n");
+
+ if (memcmp(mac, oldmac, 20) != 0) {
+ fprintf(stderr,
+ "FAIL: Hash in decrypted data different than in encrypted.\n");
+ return 1;
+ } else if (debug)
+ printf("HMAC Test 2: passed\n");
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+test_extras(int cfd)
+{
+ struct session_op sess;
+ struct crypt_op cryp;
+ uint8_t mac[AALG_MAX_RESULT_LEN];
+ uint8_t sha1_out[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
+ int i;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Use the garbage that is on the stack :-) */
+ /* memset(&data, 0, sizeof(data)); */
+
+ /* SHA1 plain test */
+ memset(mac, 0, sizeof(mac));
+
+ sess.cipher = 0;
+ sess.mac = CRYPTO_SHA1;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof("what do")-1;
+ cryp.src = (uint8_t *)"what do";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_UPDATE;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof(" ya want for nothing?")-1;
+ cryp.src = (uint8_t *)" ya want for nothing?";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_FINAL;
+
+ DO_OR_DIE(do_async_crypt(cfd, &cryp), 0);
+ DO_OR_DIE(do_async_fetch(cfd, &cryp), 0);
+
+ if (memcmp(mac, sha1_out, 20)!=0) {
+ printf("mac: ");
+ for (i=0;i<SHA1_HASH_LEN;i++) {
+ printf("%.2x", (uint8_t)mac[i]);
+ }
+ puts("\n");
+ fprintf(stderr, "HASH test [update]: failed\n");
+ } else {
+ if (debug) fprintf(stderr, "HASH test [update]: passed\n");
+ }
+
+ memset(mac, 0, sizeof(mac));
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int
+main()
+{
+ int fd = -1, cfd = -1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Clone file descriptor */
+ if (ioctl(fd, CRIOGET, &cfd)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+ if (test_crypto(cfd))
+ return 1;
+
+ if (test_extras(cfd))
+ return 1;
+
+ /* Close cloned descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
+#else
+int
+main(int argc, char** argv)
+{
+ return (0);
+}
+#endif
diff --git a/drivers/cryptodev-linux-master/tests/async_speed.c b/drivers/cryptodev-linux-master/tests/async_speed.c
new file mode 100644
index 00000000..8aa0402d
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/async_speed.c
@@ -0,0 +1,226 @@
+/* cryptodev_test - simple benchmark tool for cryptodev
+ *
+ * Copyright (C) 2010 by Phil Sutter <phil.sutter@viprinet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
+#include <crypto/cryptodev.h>
+
+#ifdef ENABLE_ASYNC
+
+static double udifftimeval(struct timeval start, struct timeval end)
+{
+ return (double)(end.tv_usec - start.tv_usec) +
+ (double)(end.tv_sec - start.tv_sec) * 1000 * 1000;
+}
+
+static volatile int must_finish;
+static struct pollfd pfd;
+
+static void alarm_handler(int signo)
+{
+ must_finish = 1;
+ pfd.events = POLLIN;
+}
+
+static char *units[] = { "", "Ki", "Mi", "Gi", "Ti", 0};
+
+static void value2human(double bytes, double time, double* data, double* speed,char* metric)
+{
+ int unit = 0;
+
+ *data = bytes;
+ while (*data > 1024 && units[unit + 1]) {
+ *data /= 1024;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", units[unit]);
+}
+
+
+int encrypt_data(struct session_op *sess, int fdc, int chunksize, int alignmask)
+{
+ struct crypt_op cop;
+ char *buffer[64], iv[32];
+ static int val = 23;
+ struct timeval start, end;
+ double total = 0;
+ double secs, ddata, dspeed;
+ char metric[16];
+ int rc, wqueue = 0, bufidx = 0;
+
+ memset(iv, 0x23, 32);
+
+ printf("\tEncrypting in chunks of %d bytes: ", chunksize);
+ fflush(stdout);
+
+ for (rc = 0; rc < 64; rc++) {
+ if (alignmask) {
+ if (posix_memalign((void **)(buffer + rc), alignmask + 1, chunksize)) {
+ printf("posix_memalign() failed!\n");
+ return 1;
+ }
+ } else {
+ if (!(buffer[rc] = malloc(chunksize))) {
+ perror("malloc()");
+ return 1;
+ }
+ }
+ memset(buffer[rc], val++, chunksize);
+ }
+ pfd.fd = fdc;
+ pfd.events = POLLOUT | POLLIN;
+
+ must_finish = 0;
+ alarm(5);
+
+ gettimeofday(&start, NULL);
+ do {
+ if ((rc = poll(&pfd, 1, 100)) < 0) {
+ if (errno & (ERESTART | EINTR))
+ continue;
+ fprintf(stderr, "errno = %d ", errno);
+ perror("poll()");
+ return 1;
+ }
+
+ if (pfd.revents & POLLOUT) {
+ memset(&cop, 0, sizeof(cop));
+ cop.ses = sess->ses;
+ cop.len = chunksize;
+ cop.iv = (unsigned char *)iv;
+ cop.op = COP_ENCRYPT;
+ cop.src = cop.dst = (unsigned char *)buffer[bufidx];
+ bufidx = (bufidx + 1) % 64;
+
+ if (ioctl(fdc, CIOCASYNCCRYPT, &cop)) {
+ perror("ioctl(CIOCASYNCCRYPT)");
+ return 1;
+ }
+ wqueue++;
+ }
+ if (pfd.revents & POLLIN) {
+ if (ioctl(fdc, CIOCASYNCFETCH, &cop)) {
+ perror("ioctl(CIOCASYNCFETCH)");
+ return 1;
+ }
+ wqueue--;
+ total += cop.len;
+ }
+ } while(!must_finish || wqueue);
+ gettimeofday(&end, NULL);
+
+ secs = udifftimeval(start, end)/ 1000000.0;
+
+ value2human(total, secs, &ddata, &dspeed, metric);
+ printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+
+ for (rc = 0; rc < 64; rc++)
+ free(buffer[rc]);
+ return 0;
+}
+
+int main(void)
+{
+ int fd, i, fdc = -1, alignmask = 0;
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ char keybuf[32];
+
+ signal(SIGALRM, alarm_handler);
+
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+ perror("open()");
+ return 1;
+ }
+ if (ioctl(fd, CRIOGET, &fdc)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ fprintf(stderr, "Testing NULL cipher: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_NULL;
+ sess.keylen = 0;
+ sess.key = (unsigned char *)keybuf;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ alignmask = siop.alignmask;
+#endif
+
+ for (i = 256; i <= (64 * 4096); i *= 2) {
+ if (encrypt_data(&sess, fdc, i, alignmask))
+ break;
+ }
+
+ fprintf(stderr, "\nTesting AES-128-CBC cipher: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = 16;
+ memset(keybuf, 0x42, 16);
+ sess.key = (unsigned char *)keybuf;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ alignmask = siop.alignmask;
+#endif
+
+ for (i = 256; i <= (64 * 1024); i *= 2) {
+ if (encrypt_data(&sess, fdc, i, alignmask))
+ break;
+ }
+
+ close(fdc);
+ close(fd);
+ return 0;
+}
+
+#else
+int
+main(int argc, char** argv)
+{
+ return (0);
+}
+#endif
diff --git a/drivers/cryptodev-linux-master/tests/asynchelper.h b/drivers/cryptodev-linux-master/tests/asynchelper.h
new file mode 100644
index 00000000..b5ab16c8
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/asynchelper.h
@@ -0,0 +1,54 @@
+#ifndef __ASYNCHELPER_H
+#define __ASYNCHELPER_H
+
+/* poll until POLLOUT, then call CIOCASYNCCRYPT */
+inline int do_async_crypt(int cfd, struct crypt_op *cryp)
+{
+ struct pollfd pfd;
+
+ pfd.fd = cfd;
+ pfd.events = POLLOUT;
+
+ if (poll(&pfd, 1, -1) < 1) {
+ perror("poll()");
+ return 1;
+ }
+
+ if (ioctl(cfd, CIOCASYNCCRYPT, cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+ return 0;
+}
+
+/* poll until POLLIN, then call CIOCASYNCFETCH */
+inline int do_async_fetch(int cfd, struct crypt_op *cryp)
+{
+ struct pollfd pfd;
+
+ pfd.fd = cfd;
+ pfd.events = POLLIN;
+
+ if (poll(&pfd, 1, -1) < 1) {
+ perror("poll()");
+ return 1;
+ }
+
+ if (ioctl(cfd, CIOCASYNCFETCH, cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+ return 0;
+}
+
+/* Check return value of stmt for identity with goodval. If they
+ * don't match, call return with the value of stmt. */
+#define DO_OR_DIE(stmt, goodval) { \
+ int __rc_val; \
+ if ((__rc_val = stmt) != goodval) { \
+ perror("DO_OR_DIE(" #stmt "," #goodval ")"); \
+ return __rc_val; \
+ } \
+}
+
+#endif /* __ASYNCHELPER_H */
diff --git a/drivers/cryptodev-linux-master/tests/cipher-aead-srtp.c b/drivers/cryptodev-linux-master/tests/cipher-aead-srtp.c
new file mode 100644
index 00000000..b1b0a219
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/cipher-aead-srtp.c
@@ -0,0 +1,595 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "testhelper.h"
+
+#define DATA_SIZE (8*1024)
+#define HEADER_SIZE 193
+#define PLAINTEXT_SIZE 1021
+#define FOOTER_SIZE 15
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+
+#define MAC_SIZE 20 /* SHA1 */
+
+static int debug = 0;
+
+static int
+get_sha1_hmac(int cfd, void* key, int key_size, void* data, int data_size, void* mac)
+{
+ struct session_op sess;
+ struct crypt_op cryp;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ sess.cipher = 0;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = key_size;
+ sess.mackey = key;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = data_size;
+ cryp.src = data;
+ cryp.dst = NULL;
+ cryp.iv = NULL;
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static void print_buf(char* desc, unsigned char* buf, int size)
+{
+int i;
+ fputs(desc, stderr);
+ for (i=0;i<size;i++) {
+ fprintf(stderr, "%.2x", (uint8_t)buf[i]);
+ }
+ fputs("\n", stderr);
+}
+
+static int
+test_crypto(int cfd)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t *payload_plain, *payload_cipher;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t sha1mac[20];
+ uint8_t tag[20];
+ uint8_t mackey[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+ int mackey_len = 16;
+ unsigned int data_size;
+
+ struct session_op sess;
+ struct crypt_op co;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+ memset(&co, 0, sizeof(co));
+
+ memset(key,0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CTR;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = mackey_len;
+ sess.mackey = mackey;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+
+ if (debug)
+ printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+ payload_plain = buf_align(plaintext + HEADER_SIZE, siop.alignmask);
+ payload_cipher = buf_align(ciphertext + HEADER_SIZE, siop.alignmask);
+
+ memset(plaintext, 0x15, HEADER_SIZE); /* header */
+ memset(payload_plain, 0x17, PLAINTEXT_SIZE); /* payload */
+ memset(payload_plain+PLAINTEXT_SIZE, 0x22, FOOTER_SIZE);
+
+ memcpy(ciphertext, plaintext, DATA_SIZE);
+
+ /* (HEADER_SIZE + payload alignment) + PLAINTEXT_SIZE + FOOTER_SIZE */
+ data_size = (payload_plain - plaintext) + PLAINTEXT_SIZE + FOOTER_SIZE;
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.len = PLAINTEXT_SIZE;
+ cao.auth_len = data_size;
+ cao.auth_src = ciphertext;
+ cao.src = payload_cipher;
+ cao.dst = cao.src;
+ cao.iv = iv;
+ cao.op = COP_ENCRYPT;
+ cao.flags = COP_FLAG_AEAD_SRTP_TYPE;
+ cao.tag = tag;
+ cao.tag_len = 20;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CTR;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ if (get_sha1_hmac(cfd, mackey, mackey_len, ciphertext, data_size, sha1mac) != 0) {
+ fprintf(stderr, "SHA1 MAC failed\n");
+ return 1;
+ }
+
+ if (memcmp(tag, sha1mac, 20) != 0) {
+ fprintf(stderr, "AEAD SHA1 MAC does not match plain MAC\n");
+ print_buf("SHA1: ", sha1mac, 20);
+ print_buf("SHA1-SRTP: ", tag, 20);
+ return 1;
+ }
+
+ /* Decrypt data.encrypted to data.decrypted */
+ co.ses = sess.ses;
+ co.len = PLAINTEXT_SIZE;
+ co.src = payload_cipher;
+ co.dst = payload_cipher;
+ co.iv = iv;
+ co.op = COP_DECRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &co)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(payload_plain, payload_cipher, PLAINTEXT_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", (unsigned int)plaintext[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", (unsigned int)ciphertext[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ if (debug) printf("Test passed\n");
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+test_encrypt_decrypt(int cfd)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t *payload_plain, *payload_cipher;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t tag[20];
+ uint8_t mackey[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+ int mackey_len = 16;
+ unsigned int data_size;
+
+ struct session_op sess;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+
+ memset(key,0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CTR;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = mackey_len;
+ sess.mackey = mackey;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+// printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+// siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+ payload_plain = buf_align(plaintext + HEADER_SIZE, siop.alignmask);
+ payload_cipher = buf_align(ciphertext + HEADER_SIZE, siop.alignmask);
+
+ memset(plaintext, 0x15, HEADER_SIZE); /* header */
+ memset(payload_plain, 0x17, PLAINTEXT_SIZE); /* payload */
+ memset(payload_plain+PLAINTEXT_SIZE, 0x22, FOOTER_SIZE);
+
+ memcpy(ciphertext, plaintext, DATA_SIZE);
+
+ /* (HEADER_SIZE + payload alignment) + PLAINTEXT_SIZE + FOOTER_SIZE */
+ data_size = (payload_plain - plaintext) + PLAINTEXT_SIZE + FOOTER_SIZE;
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.len = PLAINTEXT_SIZE;
+ cao.auth_len = data_size;
+ cao.auth_src = ciphertext;
+ cao.src = payload_cipher;
+ cao.dst = cao.src;
+ cao.iv = iv;
+ cao.op = COP_ENCRYPT;
+ cao.flags = COP_FLAG_AEAD_SRTP_TYPE;
+ cao.tag = tag;
+ cao.tag_len = 20;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CTR;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = mackey_len;
+ sess.mackey = mackey;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Decrypt data.encrypted to data.decrypted */
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.len = PLAINTEXT_SIZE;
+ cao.auth_len = data_size;
+ cao.auth_src = ciphertext;
+ cao.src = payload_cipher;
+ cao.dst = cao.src;
+ cao.iv = iv;
+ cao.op = COP_DECRYPT;
+ cao.flags = COP_FLAG_AEAD_SRTP_TYPE;
+ cao.tag = tag;
+ cao.tag_len = 20;
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(payload_plain, payload_cipher, PLAINTEXT_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", (unsigned int)plaintext[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", (unsigned int)ciphertext[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ if (debug) printf("Test passed\n");
+
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+test_encrypt_decrypt_error(int cfd, int err)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t *payload_plain, *payload_cipher;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t tag[20];
+ uint8_t mackey[] = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+ int mackey_len = 16;
+ unsigned int data_size;
+
+ struct session_op sess;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+
+ memset(key,0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CTR;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = mackey_len;
+ sess.mackey = mackey;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+// printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+// siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+ payload_plain = buf_align(plaintext + HEADER_SIZE, siop.alignmask);
+ payload_cipher = buf_align(ciphertext + HEADER_SIZE, siop.alignmask);
+
+ memset(plaintext, 0x15, HEADER_SIZE); /* header */
+ memset(payload_plain, 0x17, PLAINTEXT_SIZE); /* payload */
+ memset(payload_plain + PLAINTEXT_SIZE, 0x22, FOOTER_SIZE);
+
+ memcpy(ciphertext, plaintext, DATA_SIZE);
+
+ /* (HEADER_SIZE + payload alignment) + PLAINTEXT_SIZE + FOOTER_SIZE */
+ data_size = (payload_plain - plaintext) + PLAINTEXT_SIZE + FOOTER_SIZE;
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.len = PLAINTEXT_SIZE;
+ cao.auth_len = data_size;
+ cao.auth_src = ciphertext;
+ cao.src = payload_cipher;
+ cao.dst = cao.src;
+ cao.iv = iv;
+ cao.op = COP_ENCRYPT;
+ cao.flags = COP_FLAG_AEAD_SRTP_TYPE;
+ cao.tag = tag;
+ cao.tag_len = 20;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CTR;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = mackey_len;
+ sess.mackey = mackey;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Decrypt data.encrypted to data.decrypted */
+ /* Encrypt data.in to data.encrypted */
+ if (err == 0)
+ ciphertext[1]++;
+ else
+ payload_cipher[3]++;
+ cao.ses = sess.ses;
+ cao.len = PLAINTEXT_SIZE;
+ cao.auth_len = data_size;
+ cao.auth_src = ciphertext;
+ cao.src = payload_cipher;
+ cao.dst = cao.src;
+ cao.iv = iv;
+ cao.op = COP_DECRYPT;
+ cao.flags = COP_FLAG_AEAD_SRTP_TYPE;
+ cao.tag = tag;
+ cao.tag_len = 20;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ if (debug) printf("Test passed\n");
+ return 0;
+ }
+
+ /* Verify the result */
+ if (memcmp(payload_plain, payload_cipher, PLAINTEXT_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", (unsigned int)plaintext[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", (unsigned int)ciphertext[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ printf("Test failed\n");
+
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 1;
+}
+
+int
+main(int argc, char** argv)
+{
+ int fd = -1, cfd = -1;
+
+ if (argc > 1) debug = 1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Clone file descriptor */
+ if (ioctl(fd, CRIOGET, &cfd)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+
+ if (test_crypto(cfd))
+ return 1;
+
+ if (test_encrypt_decrypt(cfd))
+ return 1;
+
+ if (test_encrypt_decrypt_error(cfd,0))
+ return 1;
+
+ if (test_encrypt_decrypt_error(cfd,1))
+ return 1;
+
+ /* Close cloned descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/tests/cipher-aead.c b/drivers/cryptodev-linux-master/tests/cipher-aead.c
new file mode 100644
index 00000000..305b7206
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/cipher-aead.c
@@ -0,0 +1,575 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "testhelper.h"
+
+#define DATA_SIZE (8*1024)
+#define AUTH_SIZE 31
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+
+#define MAC_SIZE 20 /* SHA1 */
+
+static int debug = 0;
+
+static int
+get_sha1_hmac(int cfd, void* key, int key_size, void* data1, int data1_size, void* data2, int data2_size, void* mac)
+{
+ struct session_op sess;
+ struct crypt_op cryp;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ sess.cipher = 0;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = key_size;
+ sess.mackey = key;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = data1_size;
+ cryp.src = data1;
+ cryp.dst = NULL;
+ cryp.iv = NULL;
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_UPDATE;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ cryp.ses = sess.ses;
+ cryp.len = data2_size;
+ cryp.src = data2;
+ cryp.dst = NULL;
+ cryp.iv = NULL;
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_FINAL;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static void print_buf(char* desc, unsigned char* buf, int size)
+{
+int i;
+ fputs(desc, stdout);
+ for (i=0;i<size;i++) {
+ printf("%.2x", (uint8_t)buf[i]);
+ }
+ fputs("\n", stdout);
+}
+
+static int
+test_crypto(int cfd)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t auth[AUTH_SIZE];
+ uint8_t sha1mac[20];
+ int pad, i;
+
+ struct session_op sess;
+ struct crypt_op co;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+ memset(&co, 0, sizeof(co));
+
+ memset(key,0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+ memset(auth, 0xf1, sizeof(auth));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = (void*)key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = 16;
+ sess.mackey = (uint8_t *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug)
+ printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+ memset(plaintext, 0x15, DATA_SIZE);
+
+ if (get_sha1_hmac(cfd, sess.mackey, sess.mackeylen, auth, sizeof(auth), plaintext, DATA_SIZE, sha1mac) != 0) {
+ fprintf(stderr, "SHA1 MAC failed\n");
+ return 1;
+ }
+
+ memcpy(ciphertext, plaintext, DATA_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = DATA_SIZE;
+ cao.src = ciphertext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.op = COP_ENCRYPT;
+ cao.flags = COP_FLAG_AEAD_TLS_TYPE;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, cao.len);
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Decrypt data.encrypted to data.decrypted */
+ co.ses = sess.ses;
+ co.len = cao.len;
+ co.src = ciphertext;
+ co.dst = ciphertext;
+ co.iv = iv;
+ co.op = COP_DECRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &co)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", plaintext[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", ciphertext[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ pad = ciphertext[cao.len-1];
+ if (memcmp(&ciphertext[cao.len-MAC_SIZE-pad-1], sha1mac, 20) != 0) {
+ fprintf(stderr, "AEAD SHA1 MAC does not match plain MAC\n");
+ print_buf("SHA1: ", sha1mac, 20);
+ print_buf("SHA1-TLS: ", &ciphertext[cao.len-MAC_SIZE-pad-1], 20);
+ return 1;
+ }
+
+
+ for (i=0;i<pad;i++)
+ if (ciphertext[cao.len-1-i] != pad) {
+ fprintf(stderr, "Pad does not match (expected %d)\n", pad);
+ print_buf("PAD: ", &ciphertext[cao.len-1-pad], pad);
+ return 1;
+ }
+
+ if (debug) printf("Test passed\n");
+
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+test_encrypt_decrypt(int cfd)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t auth[AUTH_SIZE];
+ uint8_t sha1mac[20];
+ int enc_len;
+
+ struct session_op sess;
+ struct crypt_op co;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+ memset(&co, 0, sizeof(co));
+
+ memset(key,0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+ memset(auth, 0xf1, sizeof(auth));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = 16;
+ sess.mackey = (uint8_t *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+// printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+// siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+
+ memset(plaintext, 0x15, DATA_SIZE);
+
+ if (get_sha1_hmac(cfd, sess.mackey, sess.mackeylen, auth, sizeof(auth), plaintext, DATA_SIZE, sha1mac) != 0) {
+ fprintf(stderr, "SHA1 MAC failed\n");
+ return 1;
+ }
+
+ memcpy(ciphertext, plaintext, DATA_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = (void*)auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = DATA_SIZE;
+ cao.src = (void*)ciphertext;
+ cao.dst = (void*)ciphertext;
+ cao.iv = iv;
+ cao.op = COP_ENCRYPT;
+ cao.flags = COP_FLAG_AEAD_TLS_TYPE;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ enc_len = cao.len;
+ //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = 16;
+ sess.mackey = (uint8_t *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = enc_len;
+ cao.src = ciphertext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.op = COP_DECRYPT;
+ cao.flags = COP_FLAG_AEAD_TLS_TYPE;
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ if (cao.len != DATA_SIZE) {
+ fprintf(stderr, "decrypted data size incorrect!\n");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", plaintext[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", ciphertext[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ if (debug) printf("Test passed\n");
+
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+test_encrypt_decrypt_error(int cfd, int err)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t auth[AUTH_SIZE];
+ uint8_t sha1mac[20];
+ int enc_len;
+
+ struct session_op sess;
+ struct crypt_op co;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+ memset(&co, 0, sizeof(co));
+
+ memset(key,0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+ memset(auth, 0xf1, sizeof(auth));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = 16;
+ sess.mackey = (uint8_t *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+// printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+// siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+ memset(plaintext, 0x15, DATA_SIZE);
+
+ if (get_sha1_hmac(cfd, sess.mackey, sess.mackeylen, auth, sizeof(auth), plaintext, DATA_SIZE, sha1mac) != 0) {
+ fprintf(stderr, "SHA1 MAC failed\n");
+ return 1;
+ }
+
+ memcpy(ciphertext, plaintext, DATA_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = DATA_SIZE;
+ cao.src = ciphertext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.op = COP_ENCRYPT;
+ cao.flags = COP_FLAG_AEAD_TLS_TYPE;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ enc_len = cao.len;
+ //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = 16;
+ sess.mackey = (uint8_t *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ if (err == 0)
+ auth[2]++;
+ else
+ ciphertext[4]++;
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = enc_len;
+ cao.src = ciphertext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.op = COP_DECRYPT;
+ cao.flags = COP_FLAG_AEAD_TLS_TYPE;
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ if (debug) printf("Test passed\n");
+ return 0;
+ }
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+
+ fprintf(stderr, "Modification to ciphertext was not detected\n");
+ return 1;
+}
+
+int
+main()
+{
+ int fd = -1, cfd = -1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Clone file descriptor */
+ if (ioctl(fd, CRIOGET, &cfd)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+
+ if (test_crypto(cfd))
+ return 1;
+
+ if (test_encrypt_decrypt(cfd))
+ return 1;
+
+ if (test_encrypt_decrypt_error(cfd, 0))
+ return 1;
+
+ if (test_encrypt_decrypt_error(cfd, 1))
+ return 1;
+
+ /* Close cloned descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/tests/cipher-gcm.c b/drivers/cryptodev-linux-master/tests/cipher-gcm.c
new file mode 100644
index 00000000..36c827ac
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/cipher-gcm.c
@@ -0,0 +1,522 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "testhelper.h"
+
+#define DATA_SIZE (8*1024)
+#define AUTH_SIZE 31
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+
+#define my_perror(x) {fprintf(stderr, "%s: %d\n", __func__, __LINE__); perror(x); }
+
+static int debug = 0;
+
+static void print_buf(char *desc, const unsigned char *buf, int size)
+{
+ int i;
+ fputs(desc, stdout);
+ for (i = 0; i < size; i++) {
+ printf("%.2x", (uint8_t) buf[i]);
+ }
+ fputs("\n", stdout);
+}
+
+struct aes_gcm_vectors_st {
+ const uint8_t *key;
+ const uint8_t *auth;
+ int auth_size;
+ const uint8_t *plaintext;
+ int plaintext_size;
+ const uint8_t *iv;
+ const uint8_t *ciphertext;
+ const uint8_t *tag;
+};
+
+struct aes_gcm_vectors_st aes_gcm_vectors[] = {
+ {
+ .key = (uint8_t *)
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .auth = NULL,
+ .auth_size = 0,
+ .plaintext = (uint8_t *)
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .plaintext_size = 16,
+ .ciphertext = (uint8_t *)
+ "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78",
+ .iv = (uint8_t *)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ .tag = (uint8_t *)
+ "\xab\x6e\x47\xd4\x2c\xec\x13\xbd\xf5\x3a\x67\xb2\x12\x57\xbd\xdf"
+ },
+ {
+ .key = (uint8_t *)
+ "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .auth = NULL,
+ .auth_size = 0,
+ .plaintext = (uint8_t *)
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55",
+ .plaintext_size = 64,
+ .ciphertext = (uint8_t *)
+ "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85",
+ .iv = (uint8_t *)"\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+ .tag = (uint8_t *)"\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4"
+ },
+ {
+ .key = (uint8_t *)
+ "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+ .auth = (uint8_t *)
+ "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef\xab\xad\xda\xd2",
+ .auth_size = 20,
+ .plaintext = (uint8_t *)
+ "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39",
+ .plaintext_size = 60,
+ .ciphertext = (uint8_t *)
+ "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91",
+ .iv = (uint8_t *)"\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+ .tag = (uint8_t *)
+ "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb\x94\xfa\xe9\x5a\xe7\x12\x1a\x47"
+ }
+};
+
+
+/* Test against AES-GCM test vectors.
+ */
+static int test_crypto(int cfd)
+{
+ int i;
+ uint8_t tmp[128];
+
+ struct session_op sess;
+ struct crypt_auth_op cao;
+
+ /* Get crypto session for AES128 */
+
+ if (debug) {
+ fprintf(stdout, "Tests on AES-GCM vectors: ");
+ fflush(stdout);
+ }
+ for (i = 0;
+ i < sizeof(aes_gcm_vectors) / sizeof(aes_gcm_vectors[0]);
+ i++) {
+ memset(&sess, 0, sizeof(sess));
+ memset(tmp, 0, sizeof(tmp));
+
+ sess.cipher = CRYPTO_AES_GCM;
+ sess.keylen = 16;
+ sess.key = (void *) aes_gcm_vectors[i].key;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ my_perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ memset(&cao, 0, sizeof(cao));
+
+ cao.ses = sess.ses;
+ cao.dst = tmp;
+ cao.iv = (void *) aes_gcm_vectors[i].iv;
+ cao.iv_len = 12;
+ cao.op = COP_ENCRYPT;
+ cao.flags = 0;
+
+ if (aes_gcm_vectors[i].auth_size > 0) {
+ cao.auth_src = (void *) aes_gcm_vectors[i].auth;
+ cao.auth_len = aes_gcm_vectors[i].auth_size;
+ }
+
+ if (aes_gcm_vectors[i].plaintext_size > 0) {
+ cao.src = (void *) aes_gcm_vectors[i].plaintext;
+ cao.len = aes_gcm_vectors[i].plaintext_size;
+ }
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ my_perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ if (aes_gcm_vectors[i].plaintext_size > 0)
+ if (memcmp
+ (tmp, aes_gcm_vectors[i].ciphertext,
+ aes_gcm_vectors[i].plaintext_size) != 0) {
+ fprintf(stderr,
+ "AES-GCM test vector %d failed!\n",
+ i);
+
+ print_buf("Cipher: ", tmp, aes_gcm_vectors[i].plaintext_size);
+ print_buf("Expected: ", aes_gcm_vectors[i].ciphertext, aes_gcm_vectors[i].plaintext_size);
+ return 1;
+ }
+
+ if (memcmp
+ (&tmp[cao.len - cao.tag_len], aes_gcm_vectors[i].tag,
+ 16) != 0) {
+ fprintf(stderr,
+ "AES-GCM test vector %d failed (tag)!\n",
+ i);
+
+ print_buf("Tag: ", &tmp[cao.len - cao.tag_len], cao.tag_len);
+ print_buf("Expected tag: ",
+ aes_gcm_vectors[i].tag, 16);
+ return 1;
+ }
+
+ }
+
+ if (debug) {
+ fprintf(stdout, "ok\n");
+ fprintf(stdout, "\n");
+ }
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ my_perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Checks if encryption and subsequent decryption
+ * produces the same data.
+ */
+static int test_encrypt_decrypt(int cfd)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t auth[AUTH_SIZE];
+ int enc_len;
+
+ struct session_op sess;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ if (debug) {
+ fprintf(stdout, "Tests on AES-GCM encryption/decryption: ");
+ fflush(stdout);
+ }
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+
+ memset(key, 0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+ memset(auth, 0xf1, sizeof(auth));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_GCM;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ my_perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ my_perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+// printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+// siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = (uint8_t *)buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = (uint8_t *)buf_align(ciphertext_raw, siop.alignmask);
+
+ memset(plaintext, 0x15, DATA_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = DATA_SIZE;
+ cao.src = plaintext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.iv_len = 12;
+ cao.op = COP_ENCRYPT;
+ cao.flags = 0;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ my_perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ enc_len = cao.len;
+ //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ my_perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_GCM;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ my_perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = enc_len;
+ cao.src = ciphertext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.iv_len = 12;
+ cao.op = COP_DECRYPT;
+ cao.flags = 0;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ my_perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ if (cao.len != DATA_SIZE) {
+ fprintf(stderr, "decrypted data size incorrect!\n");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", plaintext[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", ciphertext[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ my_perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ if (debug) {
+ fprintf(stdout, "ok\n");
+ fprintf(stdout, "\n");
+ }
+
+ return 0;
+}
+
+static int test_encrypt_decrypt_error(int cfd, int err)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+ uint8_t auth[AUTH_SIZE];
+ int enc_len;
+
+ struct session_op sess;
+ struct crypt_op co;
+ struct crypt_auth_op cao;
+ struct session_info_op siop;
+
+ if (debug) {
+ fprintf(stdout, "Tests on AES-GCM tag verification: ");
+ fflush(stdout);
+ }
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cao, 0, sizeof(cao));
+ memset(&co, 0, sizeof(co));
+
+ memset(key, 0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+ memset(auth, 0xf1, sizeof(auth));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = 16;
+ sess.mackey =
+ (uint8_t *)
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ my_perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ my_perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+// printf("requested cipher CRYPTO_AES_CBC/HMAC-SHA1, got %s with driver %s\n",
+// siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = (uint8_t *)buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = (uint8_t *)buf_align(ciphertext_raw, siop.alignmask);
+
+ memset(plaintext, 0x15, DATA_SIZE);
+ memcpy(ciphertext, plaintext, DATA_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = DATA_SIZE;
+ cao.src = ciphertext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.op = COP_ENCRYPT;
+ cao.flags = COP_FLAG_AEAD_TLS_TYPE;
+
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ my_perror("ioctl(CIOCAUTHCRYPT)");
+ return 1;
+ }
+
+ enc_len = cao.len;
+ //printf("Original plaintext size: %d, ciphertext: %d\n", DATA_SIZE, enc_len);
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ my_perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ /* Get crypto session for AES128 */
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.mackeylen = 16;
+ sess.mackey =
+ (uint8_t *)
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ my_perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ if (err == 0)
+ auth[2]++;
+ else
+ ciphertext[4]++;
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cao.ses = sess.ses;
+ cao.auth_src = auth;
+ cao.auth_len = sizeof(auth);
+ cao.len = enc_len;
+ cao.src = ciphertext;
+ cao.dst = ciphertext;
+ cao.iv = iv;
+ cao.op = COP_DECRYPT;
+ cao.flags = COP_FLAG_AEAD_TLS_TYPE;
+ if (ioctl(cfd, CIOCAUTHCRYPT, &cao)) {
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ my_perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ if (debug) {
+ fprintf(stdout, "ok\n");
+ fprintf(stdout, "\n");
+ }
+ return 0;
+ }
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ my_perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+
+ fprintf(stderr, "Modification to ciphertext was not detected\n");
+ return 1;
+}
+
+int main(int argc, char** argv)
+{
+ int fd = -1, cfd = -1;
+
+ if (argc > 1) debug = 1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ my_perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Clone file descriptor */
+ if (ioctl(fd, CRIOGET, &cfd)) {
+ my_perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ my_perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+
+ if (test_crypto(cfd))
+ return 1;
+
+ if (test_encrypt_decrypt(cfd))
+ return 1;
+
+ if (test_encrypt_decrypt_error(cfd, 0))
+ return 1;
+
+ if (test_encrypt_decrypt_error(cfd, 1))
+ return 1;
+
+ /* Close cloned descriptor */
+ if (close(cfd)) {
+ my_perror("close(cfd)");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ my_perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/cipher.c b/drivers/cryptodev-linux-master/tests/cipher.c
new file mode 100644
index 00000000..fab3de6b
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/cipher.c
@@ -0,0 +1,327 @@
+/*
+ * Demo on how to use /dev/crypto device for ciphering.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+#include "testhelper.h"
+
+static int debug = 0;
+
+#define DATA_SIZE 8*1024
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+
+static int
+test_crypto(int cfd)
+{
+ uint8_t plaintext_raw[DATA_SIZE + 63], *plaintext;
+ uint8_t ciphertext_raw[DATA_SIZE + 63], *ciphertext;
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t key[KEY_SIZE];
+
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ struct crypt_op cryp;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ memset(key, 0x33, sizeof(key));
+ memset(iv, 0x03, sizeof(iv));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug)
+ printf("requested cipher CRYPTO_AES_CBC, got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext = buf_align(plaintext_raw, siop.alignmask);
+ ciphertext = buf_align(ciphertext_raw, siop.alignmask);
+#else
+ plaintext = plaintext_raw;
+ ciphertext = ciphertext_raw;
+#endif
+ memset(plaintext, 0x15, DATA_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = DATA_SIZE;
+ cryp.src = plaintext;
+ cryp.dst = ciphertext;
+ cryp.iv = iv;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug)
+ printf("requested cipher CRYPTO_AES_CBC, got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+#endif
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cryp.ses = sess.ses;
+ cryp.len = DATA_SIZE;
+ cryp.src = ciphertext;
+ cryp.dst = ciphertext;
+ cryp.iv = iv;
+ cryp.op = COP_DECRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(plaintext, ciphertext, DATA_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", plaintext[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < DATA_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", ciphertext[i]);
+ }
+ printf("\n");
+ return 1;
+ } else if (debug)
+ printf("Test passed\n");
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int test_aes(int cfd)
+{
+ uint8_t plaintext1_raw[BLOCK_SIZE + 63], *plaintext1;
+ uint8_t ciphertext1[BLOCK_SIZE] = { 0xdf, 0x55, 0x6a, 0x33, 0x43, 0x8d, 0xb8, 0x7b, 0xc4, 0x1b, 0x17, 0x52, 0xc5, 0x5e, 0x5e, 0x49 };
+ uint8_t iv1[BLOCK_SIZE];
+ uint8_t key1[KEY_SIZE] = { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ uint8_t plaintext2_data[BLOCK_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 };
+ uint8_t plaintext2_raw[BLOCK_SIZE + 63], *plaintext2;
+ uint8_t ciphertext2[BLOCK_SIZE] = { 0xb7, 0x97, 0x2b, 0x39, 0x41, 0xc4, 0x4b, 0x90, 0xaf, 0xa7, 0xb2, 0x64, 0xbf, 0xba, 0x73, 0x87 };
+ uint8_t iv2[BLOCK_SIZE];
+ uint8_t key2[KEY_SIZE];
+
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ struct crypt_op cryp;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key1;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ plaintext1 = buf_align(plaintext1_raw, siop.alignmask);
+#else
+ plaintext1 = plaintext1_raw;
+#endif
+ memset(plaintext1, 0x0, BLOCK_SIZE);
+ memset(iv1, 0x0, sizeof(iv1));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = BLOCK_SIZE;
+ cryp.src = plaintext1;
+ cryp.dst = plaintext1;
+ cryp.iv = iv1;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(plaintext1, ciphertext1, BLOCK_SIZE) != 0) {
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ return 1;
+ }
+
+ /* Test 2 */
+
+ memset(key2, 0x0, sizeof(key2));
+ memset(iv2, 0x0, sizeof(iv2));
+
+ /* Get crypto session for AES128 */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key2;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug)
+ printf("requested cipher CRYPTO_AES_CBC, got %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
+
+ plaintext2 = buf_align(plaintext2_raw, siop.alignmask);
+#else
+ plaintext2 = plaintext2_raw;
+#endif
+ memcpy(plaintext2, plaintext2_data, BLOCK_SIZE);
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = BLOCK_SIZE;
+ cryp.src = plaintext2;
+ cryp.dst = plaintext2;
+ cryp.iv = iv2;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(plaintext2, ciphertext2, BLOCK_SIZE) != 0) {
+ int i;
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ printf("plaintext:");
+ for (i = 0; i < BLOCK_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", plaintext2[i]);
+ }
+ printf("ciphertext:");
+ for (i = 0; i < BLOCK_SIZE; i++) {
+ if ((i % 30) == 0)
+ printf("\n");
+ printf("%02x ", ciphertext2[i]);
+ }
+ printf("\n");
+ return 1;
+ }
+
+ if (debug) printf("AES Test passed\n");
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char** argv)
+{
+ int fd = -1, cfd = -1;
+
+ if (argc > 1) debug = 1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Clone file descriptor */
+ if (ioctl(fd, CRIOGET, &cfd)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+ if (test_aes(cfd))
+ return 1;
+
+ if (test_crypto(cfd))
+ return 1;
+
+ /* Close cloned descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/tests/cipher_comp.c b/drivers/cryptodev-linux-master/tests/cipher_comp.c
new file mode 100644
index 00000000..dbf99778
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/cipher_comp.c
@@ -0,0 +1,159 @@
+/*
+ * Compare encryption results with ones from openssl.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "openssl_wrapper.h"
+
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+#define MAX_DATALEN (64 * 1024)
+
+
+static int
+test_crypto(int cfd, struct session_op *sess, int datalen)
+{
+ uint8_t *data, *encrypted;
+ uint8_t *encrypted_comp;
+
+ uint8_t iv_in[BLOCK_SIZE];
+ uint8_t iv[BLOCK_SIZE];
+ uint8_t iv_comp[BLOCK_SIZE];
+
+ struct crypt_op cryp;
+
+ int ret = 0;
+
+ data = malloc(datalen);
+ encrypted = malloc(datalen);
+ encrypted_comp = malloc(datalen);
+ memset(data, datalen & 0xff, datalen);
+ memset(encrypted, 0x27, datalen);
+ memset(encrypted_comp, 0x41, datalen);
+
+ memset(iv_in, 0x23, sizeof(iv_in));
+ memcpy(iv, iv_in, sizeof(iv));
+ memcpy(iv_comp, iv_in, sizeof(iv_comp));
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess->ses;
+ cryp.len = datalen;
+ cryp.src = data;
+ cryp.dst = encrypted;
+ cryp.iv = iv;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_WRITE_IV;
+ if ((ret = ioctl(cfd, CIOCCRYPT, &cryp))) {
+ perror("ioctl(CIOCCRYPT)");
+ goto out;
+ }
+
+ cryp.dst = encrypted_comp;
+ cryp.iv = iv_comp;
+
+ if ((ret = openssl_cioccrypt(sess, &cryp))) {
+ fprintf(stderr, "openssl_cioccrypt() failed!\n");
+ goto out;
+ }
+
+ if ((ret = memcmp(encrypted, encrypted_comp, cryp.len))) {
+ printf("fail for datalen %d, cipher texts do not match!\n", datalen);
+ }
+ if ((ret = memcmp(iv, iv_comp, BLOCK_SIZE))) {
+ printf("fail for datalen %d, IVs do not match!\n", datalen);
+ }
+out:
+ free(data);
+ free(encrypted);
+ free(encrypted_comp);
+ return ret;
+}
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ struct session_op sess;
+ uint8_t key[KEY_SIZE];
+ int datalen = BLOCK_SIZE;
+ int datalen_end = MAX_DATALEN;
+ int i;
+
+ if (argc > 1) {
+ datalen = min(max(atoi(argv[1]), BLOCK_SIZE), MAX_DATALEN);
+ datalen_end = datalen;
+ }
+ if (argc > 2) {
+ datalen_end = min(atoi(argv[2]), MAX_DATALEN);
+ if (datalen_end < datalen)
+ datalen_end = datalen;
+ }
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ for (i = 0; i < KEY_SIZE; i++)
+ key[i] = i & 0xff;
+ memset(&sess, 0, sizeof(sess));
+
+ /* encryption test */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+ if (ioctl(fd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ {
+ struct session_info_op siop = {
+ .ses = sess.ses,
+ };
+
+ if (ioctl(fd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ } else {
+ printf("requested cipher CRYPTO_AES_CBC and mac CRYPTO_SHA1_HMAC,"
+ " got cipher %s with driver %s and hash %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name,
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ }
+ }
+#endif
+
+ for (; datalen <= datalen_end; datalen += BLOCK_SIZE) {
+ if (test_crypto(fd, &sess, datalen)) {
+ printf("test_crypto() failed for datalen of %d\n", datalen);
+ return 1;
+ }
+ }
+
+ /* Finish crypto session */
+ if (ioctl(fd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/fullspeed.c b/drivers/cryptodev-linux-master/tests/fullspeed.c
new file mode 100644
index 00000000..4e97965f
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/fullspeed.c
@@ -0,0 +1,185 @@
+/* cryptodev_test - simple benchmark tool for cryptodev
+ *
+ * Copyright (C) 2010 by Phil Sutter <phil.sutter@viprinet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <crypto/cryptodev.h>
+
+static int si = 1; /* SI by default */
+
+static double udifftimeval(struct timeval start, struct timeval end)
+{
+ return (double)(end.tv_usec - start.tv_usec) +
+ (double)(end.tv_sec - start.tv_sec) * 1000 * 1000;
+}
+
+static int must_finish = 0;
+
+static void alarm_handler(int signo)
+{
+ must_finish = 1;
+}
+
+static char *units[] = { "", "Ki", "Mi", "Gi", "Ti", 0};
+static char *si_units[] = { "", "K", "M", "G", "T", 0};
+
+static void value2human(int si, double bytes, double time, double* data, double* speed,char* metric)
+{
+ int unit = 0;
+
+ *data = bytes;
+
+ if (si) {
+ while (*data > 1000 && si_units[unit + 1]) {
+ *data /= 1000;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", si_units[unit]);
+ } else {
+ while (*data > 1024 && units[unit + 1]) {
+ *data /= 1024;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", units[unit]);
+ }
+}
+
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+int encrypt_data(int algo, void* keybuf, int key_size, int fdc, int chunksize)
+{
+ struct crypt_op cop;
+ uint8_t *buffer, iv[32];
+ static int val = 23;
+ struct timeval start, end;
+ double total = 0;
+ double secs, ddata, dspeed;
+ char metric[16];
+ struct session_op sess;
+
+ if (posix_memalign((void **)&buffer, 16, chunksize)) {
+ printf("posix_memalign() failed! (mask %x, size: %d)\n", 16, chunksize);
+ return 1;
+ }
+
+ memset(iv, 0x23, 32);
+
+ printf("\tEncrypting in chunks of %d bytes: ", chunksize);
+ fflush(stdout);
+
+ memset(buffer, val++, chunksize);
+
+ must_finish = 0;
+ alarm(5);
+
+ gettimeofday(&start, NULL);
+ do {
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = algo;
+ sess.keylen = key_size;
+ sess.key = keybuf;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+ memset(&cop, 0, sizeof(cop));
+ cop.ses = sess.ses;
+ cop.len = chunksize;
+ cop.iv = (unsigned char *)iv;
+ cop.op = COP_ENCRYPT;
+ cop.src = (unsigned char *)buffer;
+ cop.dst = buffer;
+
+ if (ioctl(fdc, CIOCCRYPT, &cop)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ ioctl(fdc, CIOCFSESSION, &sess.ses);
+
+ total+=chunksize;
+ } while(must_finish==0);
+ gettimeofday(&end, NULL);
+
+ secs = udifftimeval(start, end)/ 1000000.0;
+
+ value2human(si, total, secs, &ddata, &dspeed, metric);
+ printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+
+ free(buffer);
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ int fd, i, fdc = -1;
+ char keybuf[32];
+
+ signal(SIGALRM, alarm_handler);
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
+ printf("Usage: speed [--kib]\n");
+ exit(0);
+ }
+ if (strcmp(argv[1], "--kib") == 0) {
+ si = 0;
+ }
+ }
+
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+ perror("open()");
+ return 1;
+ }
+ if (ioctl(fd, CRIOGET, &fdc)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ fprintf(stderr, "Testing NULL cipher: \n");
+
+ for (i = 512; i <= (64 * 1024); i *= 2) {
+ if (encrypt_data(CRYPTO_NULL, keybuf, 0, fdc, i))
+ break;
+ }
+
+ fprintf(stderr, "\nTesting AES-128-CBC cipher: \n");
+ memset(keybuf, 0x42, 16);
+
+ for (i = 512; i <= (64 * 1024); i *= 2) {
+ if (encrypt_data(CRYPTO_AES_CBC, keybuf, 16, fdc, i))
+ break;
+ }
+
+ close(fdc);
+ close(fd);
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/hash_comp.c b/drivers/cryptodev-linux-master/tests/hash_comp.c
new file mode 100644
index 00000000..73f85ede
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/hash_comp.c
@@ -0,0 +1,147 @@
+/*
+ * Compare digest results with ones from openssl.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "openssl_wrapper.h"
+
+#define BLOCK_SIZE 16
+#define MAX_DATALEN (64 * 1024)
+
+static void printhex(unsigned char *buf, int buflen)
+{
+ while (buflen-- > 0) {
+ printf("\\x%.2x", *(buf++));
+ }
+ printf("\n");
+}
+
+static int
+test_crypto(int cfd, struct session_op *sess, int datalen)
+{
+ uint8_t *data;
+ uint8_t mac[AALG_MAX_RESULT_LEN];
+ uint8_t mac_comp[AALG_MAX_RESULT_LEN];
+
+ struct crypt_op cryp;
+
+ int ret = 0;
+
+ data = malloc(datalen);
+ memset(data, datalen & 0xff, datalen);
+
+ memset(mac, 0, sizeof(mac));
+ memset(mac_comp, 0, sizeof(mac_comp));
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess->ses;
+ cryp.len = datalen;
+ cryp.src = data;
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ if ((ret = ioctl(cfd, CIOCCRYPT, &cryp))) {
+ perror("ioctl(CIOCCRYPT)");
+ goto out;
+ }
+
+ cryp.mac = mac_comp;
+
+ if ((ret = openssl_cioccrypt(sess, &cryp))) {
+ fprintf(stderr, "openssl_cioccrypt() failed!\n");
+ goto out;
+ }
+
+ if (memcmp(mac, mac_comp, AALG_MAX_RESULT_LEN)) {
+ printf("fail for datalen %d, MACs do not match!\n", datalen);
+ ret = 1;
+ printf("wrong mac: ");
+ printhex(mac, 20);
+ printf("right mac: ");
+ printhex(mac_comp, 20);
+ }
+
+out:
+ free(data);
+ return ret;
+}
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ struct session_op sess;
+ int datalen = BLOCK_SIZE;
+ int datalen_end = MAX_DATALEN;
+
+ if (argc > 1) {
+ datalen = min(max(atoi(argv[1]), BLOCK_SIZE), MAX_DATALEN);
+ datalen_end = datalen;
+ }
+ if (argc > 2) {
+ datalen_end = min(atoi(argv[2]), MAX_DATALEN);
+ if (datalen_end < datalen)
+ datalen_end = datalen;
+ }
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ memset(&sess, 0, sizeof(sess));
+
+ /* Hash test */
+ sess.mac = CRYPTO_SHA1;
+ if (ioctl(fd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ {
+ struct session_info_op siop = {
+ .ses = sess.ses,
+ };
+
+ if (ioctl(fd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ } else {
+ printf("requested mac CRYPTO_SHA1, got hash %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ }
+ }
+#endif
+
+ for (; datalen <= datalen_end; datalen += BLOCK_SIZE) {
+ if (test_crypto(fd, &sess, datalen)) {
+ printf("test_crypto() failed for datalen of %d\n", datalen);
+ return 1;
+ }
+ }
+
+ /* Finish crypto session */
+ if (ioctl(fd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/hashcrypt_speed.c b/drivers/cryptodev-linux-master/tests/hashcrypt_speed.c
new file mode 100644
index 00000000..2b49f2b6
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/hashcrypt_speed.c
@@ -0,0 +1,207 @@
+/* hashcrypt_speed - simple SHA+AES benchmark tool for cryptodev
+ *
+ * Copyright (C) 2011 by Phil Sutter <phil.sutter@viprinet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <crypto/cryptodev.h>
+
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+static double udifftimeval(struct timeval start, struct timeval end)
+{
+ return (double)(end.tv_usec - start.tv_usec) +
+ (double)(end.tv_sec - start.tv_sec) * 1000 * 1000;
+}
+
+static int must_finish = 0;
+
+static void alarm_handler(int signo)
+{
+ must_finish = 1;
+}
+
+static char *units[] = { "", "Ki", "Mi", "Gi", "Ti", 0};
+static char *si_units[] = { "", "K", "M", "G", "T", 0};
+
+static void value2human(int si, double bytes, double time, double* data, double* speed,char* metric)
+{
+ int unit = 0;
+
+ *data = bytes;
+
+ if (si) {
+ while (*data > 1000 && si_units[unit + 1]) {
+ *data /= 1000;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", si_units[unit]);
+ } else {
+ while (*data > 1024 && units[unit + 1]) {
+ *data /= 1024;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", units[unit]);
+ }
+}
+
+
+int hash_data(struct session_op *sess, int fdc, int chunksize, int align)
+{
+ struct crypt_op cop;
+ char *buffer;
+ static int val = 23;
+ struct timeval start, end;
+ double total = 0;
+ double secs, ddata, dspeed;
+ char metric[16];
+ uint8_t mac[AALG_MAX_RESULT_LEN];
+
+ if (align) {
+ if (posix_memalign((void **)&buffer, align, chunksize)) {
+ printf("posix_memalign() failed, align: %d, size: %d!\n", align, chunksize);
+ return 1;
+ }
+ } else {
+ if (!(buffer = malloc(chunksize))) {
+ perror("malloc()");
+ return 1;
+ }
+ }
+
+ printf("\tEncrypting in chunks of %d bytes: ", chunksize);
+ fflush(stdout);
+
+ memset(buffer, val++, chunksize);
+
+ must_finish = 0;
+ alarm(5);
+
+ gettimeofday(&start, NULL);
+ do {
+ memset(&cop, 0, sizeof(cop));
+ cop.ses = sess->ses;
+ cop.len = chunksize;
+ cop.op = COP_ENCRYPT;
+ cop.src = cop.dst = (unsigned char *)buffer;
+ cop.mac = mac;
+
+ if (ioctl(fdc, CIOCCRYPT, &cop)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+ total+=chunksize;
+ } while(must_finish==0);
+ gettimeofday(&end, NULL);
+
+ secs = udifftimeval(start, end)/ 1000000.0;
+
+ value2human(1, total, secs, &ddata, &dspeed, metric);
+ printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+
+ free(buffer);
+ return 0;
+}
+
+int main(void)
+{
+ int fd, i, fdc = -1, align = 0;
+ struct session_op sess;
+ char keybuf[32];
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ signal(SIGALRM, alarm_handler);
+
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+ perror("open()");
+ return 1;
+ }
+ if (ioctl(fd, CRIOGET, &fdc)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ fprintf(stderr, "Testing AES128 with SHA1 Hash: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = 16;
+ memset(keybuf, 0x42, 32);
+ sess.key = (unsigned char *)keybuf;
+ sess.mac = CRYPTO_SHA1;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ printf("requested hash CRYPTO_SHA1, got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ align = MAX(sizeof(void*), siop.alignmask+1);
+#endif
+
+ for (i = 256; i <= (64 * 1024); i *= 4) {
+ if (hash_data(&sess, fdc, i, align))
+ break;
+ }
+
+ fprintf(stderr, "\nTesting AES256 with SHA256 Hash: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = 32;
+ sess.key = (unsigned char *)keybuf;
+ sess.mac = CRYPTO_SHA2_256;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ printf("requested hash CRYPTO_SHA2_256, got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ align = MAX(sizeof(void*), siop.alignmask+1);
+#endif
+
+ for (i = 256; i <= (64 * 1024); i *= 4) {
+ if (hash_data(&sess, fdc, i, align))
+ break;
+ }
+
+ close(fdc);
+ close(fd);
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/hmac.c b/drivers/cryptodev-linux-master/tests/hmac.c
new file mode 100644
index 00000000..8d6492e1
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/hmac.c
@@ -0,0 +1,336 @@
+/*
+ * Demo on how to use /dev/crypto device for HMAC.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+static int debug = 0;
+
+#define DATA_SIZE 4096
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+#define SHA1_HASH_LEN 20
+
+static int
+test_crypto(int cfd)
+{
+ struct {
+ uint8_t in[DATA_SIZE],
+ encrypted[DATA_SIZE],
+ decrypted[DATA_SIZE],
+ iv[BLOCK_SIZE],
+ key[KEY_SIZE];
+ } data;
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ struct crypt_op cryp;
+ uint8_t mac[AALG_MAX_RESULT_LEN];
+ uint8_t oldmac[AALG_MAX_RESULT_LEN];
+ uint8_t md5_hmac_out[] = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38";
+ uint8_t sha1_out[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
+ int i;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Use the garbage that is on the stack :-) */
+ /* memset(&data, 0, sizeof(data)); */
+
+ /* SHA1 plain test */
+ memset(mac, 0, sizeof(mac));
+
+ sess.cipher = 0;
+ sess.mac = CRYPTO_SHA1;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug) printf("requested mac CRYPTO_SHA1, got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+#endif
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof("what do ya want for nothing?")-1;
+ cryp.src = (uint8_t *)"what do ya want for nothing?";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ if (memcmp(mac, sha1_out, 20)!=0) {
+ printf("mac: ");
+ for (i=0;i<SHA1_HASH_LEN;i++) {
+ printf("%.2x", (uint8_t)mac[i]);
+ }
+ puts("\n");
+ fprintf(stderr, "HASH test 1: failed\n");
+ } else {
+ if (debug) fprintf(stderr, "HASH test 1: passed\n");
+ }
+
+ /* MD5-HMAC test */
+ memset(mac, 0, sizeof(mac));
+
+ sess.cipher = 0;
+ sess.mackey = (uint8_t *)"Jefe";
+ sess.mackeylen = 4;
+ sess.mac = CRYPTO_MD5_HMAC;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug)
+ printf("requested mac CRYPTO_MD5_HMAC, got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+#endif
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof("what do ya want for nothing?")-1;
+ cryp.src = (uint8_t *)"what do ya want for nothing?";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ if (memcmp(mac, md5_hmac_out, 16)!=0) {
+ printf("mac: ");
+ for (i=0;i<SHA1_HASH_LEN;i++) {
+ printf("%.2x", (uint8_t)mac[i]);
+ }
+ puts("\n");
+ fprintf(stderr, "HMAC test 1: failed\n");
+ } else {
+ if (debug) fprintf(stderr, "HMAC test 1: passed\n");
+ }
+
+ /* Hash and encryption in one step test */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.keylen = KEY_SIZE;
+ sess.key = data.key;
+ sess.mackeylen = 16;
+ sess.mackey = (uint8_t *)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug)
+ printf("requested cipher CRYPTO_AES_CBC and mac CRYPTO_SHA1_HMAC,"
+ " got cipher %s with driver %s and hash %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name,
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+#endif
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess.ses;
+ cryp.len = sizeof(data.in);
+ cryp.src = data.in;
+ cryp.dst = data.encrypted;
+ cryp.iv = data.iv;
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ memcpy(oldmac, mac, sizeof(mac));
+
+ /* Decrypt data.encrypted to data.decrypted */
+ cryp.src = data.encrypted;
+ cryp.dst = data.decrypted;
+ cryp.op = COP_DECRYPT;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ /* Verify the result */
+ if (memcmp(data.in, data.decrypted, sizeof(data.in)) != 0) {
+ fprintf(stderr,
+ "FAIL: Decrypted data are different from the input data.\n");
+ return 1;
+ } else if (debug) printf("Crypt Test: passed\n");
+
+ if (memcmp(mac, oldmac, 20) != 0) {
+ fprintf(stderr,
+ "FAIL: Hash in decrypted data different than in encrypted.\n");
+ return 1;
+ } else if (debug) printf("HMAC Test 2: passed\n");
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+test_extras(int cfd)
+{
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ struct crypt_op cryp;
+ uint8_t mac[AALG_MAX_RESULT_LEN];
+ uint8_t sha1_out[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32";
+ int i;
+
+ memset(&sess, 0, sizeof(sess));
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Use the garbage that is on the stack :-) */
+ /* memset(&data, 0, sizeof(data)); */
+
+ /* SHA1 plain test */
+ memset(mac, 0, sizeof(mac));
+
+ sess.cipher = 0;
+ sess.mac = CRYPTO_SHA1;
+ if (ioctl(cfd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(cfd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ if (debug)
+ printf("requested mac CRYPTO_SHA1, got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+#endif
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof("what do")-1;
+ cryp.src = (uint8_t *)"what do";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_UPDATE;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ cryp.ses = sess.ses;
+ cryp.len = sizeof(" ya want for nothing?")-1;
+ cryp.src = (uint8_t *)" ya want for nothing?";
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_FINAL;
+ if (ioctl(cfd, CIOCCRYPT, &cryp)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+
+ if (memcmp(mac, sha1_out, 20)!=0) {
+ printf("mac: ");
+ for (i=0;i<SHA1_HASH_LEN;i++) {
+ printf("%.2x", (uint8_t)mac[i]);
+ }
+ puts("\n");
+ fprintf(stderr, "HASH test [update]: failed\n");
+ } else {
+ if (debug) fprintf(stderr, "HASH test [update]: passed\n");
+ }
+
+ memset(mac, 0, sizeof(mac));
+
+ /* Finish crypto session */
+ if (ioctl(cfd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int
+main(int argc, char** argv)
+{
+ int fd = -1, cfd = -1;
+
+ if (argc > 1) debug = 1;
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ /* Clone file descriptor */
+ if (ioctl(fd, CRIOGET, &cfd)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ /* Set close-on-exec (not really neede here) */
+ if (fcntl(cfd, F_SETFD, 1) == -1) {
+ perror("fcntl(F_SETFD)");
+ return 1;
+ }
+
+ /* Run the test itself */
+ if (test_crypto(cfd))
+ return 1;
+
+ if (test_extras(cfd))
+ return 1;
+
+ /* Close cloned descriptor */
+ if (close(cfd)) {
+ perror("close(cfd)");
+ return 1;
+ }
+
+ /* Close the original descriptor */
+ if (close(fd)) {
+ perror("close(fd)");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/hmac_comp.c b/drivers/cryptodev-linux-master/tests/hmac_comp.c
new file mode 100644
index 00000000..a8709cbb
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/hmac_comp.c
@@ -0,0 +1,187 @@
+/*
+ * Compare HMAC results with ones from openssl.
+ *
+ * Placed under public domain.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include <sys/ioctl.h>
+#include <crypto/cryptodev.h>
+
+#include "openssl_wrapper.h"
+
+#define BLOCK_SIZE 16
+#define KEY_SIZE 16
+#define MACKEY_SIZE 20
+#define MAX_DATALEN (64 * 1024)
+
+static void printhex(unsigned char *buf, int buflen)
+{
+ while (buflen-- > 0) {
+ printf("\\x%.2x", *(buf++));
+ }
+ printf("\n");
+}
+
+static int
+test_crypto(int cfd, struct session_op *sess, int datalen)
+{
+ unsigned char *data, *encrypted;
+ unsigned char *encrypted_comp;
+
+ unsigned char iv[BLOCK_SIZE];
+ unsigned char mac[AALG_MAX_RESULT_LEN];
+
+ unsigned char iv_comp[BLOCK_SIZE];
+ unsigned char mac_comp[AALG_MAX_RESULT_LEN];
+
+ struct crypt_op cryp;
+
+ int ret = 0;
+
+ data = malloc(datalen);
+ encrypted = malloc(datalen);
+ encrypted_comp = malloc(datalen);
+ memset(data, datalen & 0xff, datalen);
+ memset(encrypted, 0x27, datalen);
+ memset(encrypted_comp, 0x28, datalen);
+
+ memset(iv, 0x23, sizeof(iv));
+ memset(iv_comp, 0x23, sizeof(iv));
+ memset(mac, 0, sizeof(mac));
+ memset(mac_comp, 1, sizeof(mac_comp));
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ /* Encrypt data.in to data.encrypted */
+ cryp.ses = sess->ses;
+ cryp.len = datalen;
+ cryp.src = data;
+ cryp.dst = encrypted;
+ cryp.iv = iv;
+ cryp.mac = mac;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_WRITE_IV;
+ if ((ret = ioctl(cfd, CIOCCRYPT, &cryp))) {
+ perror("ioctl(CIOCCRYPT)");
+ goto out;
+ }
+
+ cryp.dst = encrypted_comp;
+ cryp.mac = mac_comp;
+ cryp.iv = iv_comp;
+
+ if ((ret = openssl_cioccrypt(sess, &cryp))) {
+ fprintf(stderr, "openssl_cioccrypt() failed!\n");
+ goto out;
+ }
+
+ if ((ret = memcmp(encrypted, encrypted_comp, cryp.len))) {
+ printf("fail for datalen %d, cipher texts do not match!\n", datalen);
+ }
+ if ((ret = memcmp(iv, iv_comp, BLOCK_SIZE))) {
+ printf("fail for datalen %d, updated IVs do not match!\n", datalen);
+ }
+ if ((ret = memcmp(mac, mac_comp, AALG_MAX_RESULT_LEN))) {
+ printf("fail for datalen 0x%x, MACs do not match!\n", datalen);
+ printf("wrong mac: ");
+ printhex(mac, 20);
+ printf("right mac: ");
+ printhex(mac_comp, 20);
+
+ }
+
+out:
+ free(data);
+ free(encrypted);
+ free(encrypted_comp);
+ return ret;
+}
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+int
+main(int argc, char **argv)
+{
+ int fd;
+ struct session_op sess;
+ unsigned char key[KEY_SIZE], mackey[MACKEY_SIZE];
+ int datalen = BLOCK_SIZE;
+ int datalen_end = MAX_DATALEN;
+ int i;
+
+ if (argc > 1) {
+ datalen = min(max(atoi(argv[1]), BLOCK_SIZE), MAX_DATALEN);
+ datalen_end = datalen;
+ }
+ if (argc > 2) {
+ datalen_end = min(atoi(argv[2]), MAX_DATALEN);
+ if (datalen_end < datalen)
+ datalen_end = datalen;
+ }
+
+ /* Open the crypto device */
+ fd = open("/dev/crypto", O_RDWR, 0);
+ if (fd < 0) {
+ perror("open(/dev/crypto)");
+ return 1;
+ }
+
+ for (i = 0; i < KEY_SIZE; i++)
+ key[i] = i & 0xff;
+ for (i = 0; i < MACKEY_SIZE; i++)
+ mackey[i] = i & 0xff;
+
+ memset(&sess, 0, sizeof(sess));
+
+ /* Hash and encryption in one step test */
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.mac = CRYPTO_SHA1_HMAC;
+ sess.keylen = KEY_SIZE;
+ sess.key = key;
+ sess.mackeylen = MACKEY_SIZE;
+ sess.mackey = mackey;
+ if (ioctl(fd, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+
+#ifdef CIOCGSESSINFO
+ {
+ struct session_info_op siop = {
+ .ses = sess.ses,
+ };
+
+ if (ioctl(fd, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ } else {
+ printf("requested cipher CRYPTO_AES_CBC and mac CRYPTO_SHA1_HMAC,"
+ " got cipher %s with driver %s and hash %s with driver %s\n",
+ siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name,
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ }
+ }
+#endif
+
+ for (; datalen <= datalen_end; datalen += BLOCK_SIZE) {
+ if (test_crypto(fd, &sess, datalen)) {
+ printf("test_crypto() failed for datalen of %d\n", datalen);
+ return 1;
+ }
+ }
+
+ /* Finish crypto session */
+ if (ioctl(fd, CIOCFSESSION, &sess.ses)) {
+ perror("ioctl(CIOCFSESSION)");
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/openssl_wrapper.c b/drivers/cryptodev-linux-master/tests/openssl_wrapper.c
new file mode 100644
index 00000000..dea2496d
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/openssl_wrapper.c
@@ -0,0 +1,300 @@
+#include <crypto/cryptodev.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/opensslv.h>
+
+//#define DEBUG
+
+#ifdef DEBUG
+# define dbgp(...) { \
+ fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+}
+#else
+# define dbgp(...) /* nothing */
+#endif
+
+enum ctx_type {
+ ctx_type_none = 0,
+ ctx_type_hmac,
+ ctx_type_md,
+};
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+union openssl_ctx {
+ HMAC_CTX *hmac;
+ EVP_MD_CTX *md;
+};
+#else
+union openssl_ctx {
+ HMAC_CTX hmac;
+ EVP_MD_CTX md;
+};
+#endif
+
+struct ctx_mapping {
+ __u32 ses;
+ enum ctx_type type;
+ union openssl_ctx ctx;
+};
+
+static struct ctx_mapping ctx_map[512];
+
+static struct ctx_mapping *find_mapping(__u32 ses)
+{
+ int i;
+
+ for (i = 0; i < 512; i++) {
+ if (ctx_map[i].ses == ses)
+ return &ctx_map[i];
+ }
+ return NULL;
+}
+
+static struct ctx_mapping *new_mapping(void)
+{
+ return find_mapping(0);
+}
+
+static void remove_mapping(__u32 ses)
+{
+ struct ctx_mapping *mapping;
+
+ if (!(mapping = find_mapping(ses))) {
+ printf("%s: failed to find mapping for session %d\n", __func__, ses);
+ return;
+ }
+ switch (mapping->type) {
+ case ctx_type_none:
+ break;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ case ctx_type_hmac:
+ dbgp("%s: calling HMAC_CTX_free\n", __func__);
+ HMAC_CTX_free(mapping->ctx.hmac);
+ break;
+ case ctx_type_md:
+ dbgp("%s: calling EVP_MD_CTX_free\n", __func__);
+ EVP_MD_CTX_free(mapping->ctx.md);
+ break;
+#else
+ case ctx_type_hmac:
+ dbgp("%s: calling HMAC_CTX_cleanup\n", __func__);
+ HMAC_CTX_cleanup(&mapping->ctx.hmac);
+ break;
+ case ctx_type_md:
+ dbgp("%s: calling EVP_MD_CTX_cleanup\n", __func__);
+ EVP_MD_CTX_cleanup(&mapping->ctx.md);
+ break;
+#endif
+ }
+ memset(mapping, 0, sizeof(*mapping));
+}
+
+static union openssl_ctx *__ses_to_ctx(__u32 ses)
+{
+ struct ctx_mapping *mapping;
+
+ if (!(mapping = find_mapping(ses)))
+ return NULL;
+ return &mapping->ctx;
+}
+
+static HMAC_CTX *ses_to_hmac(__u32 ses) { return (HMAC_CTX *)__ses_to_ctx(ses); }
+static EVP_MD_CTX *ses_to_md(__u32 ses) { return (EVP_MD_CTX *)__ses_to_ctx(ses); }
+
+static const EVP_MD *sess_to_evp_md(struct session_op *sess)
+{
+ switch (sess->mac) {
+#ifndef OPENSSL_NO_MD5
+ case CRYPTO_MD5_HMAC: return EVP_md5();
+#endif
+#ifndef OPENSSL_NO_SHA
+ case CRYPTO_SHA1_HMAC:
+ case CRYPTO_SHA1:
+ return EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+ case CRYPTO_RIPEMD160_HMAC: return EVP_ripemd160();
+#endif
+#ifndef OPENSSL_NO_SHA256
+ case CRYPTO_SHA2_256_HMAC: return EVP_sha256();
+#endif
+#ifndef OPENSSL_NO_SHA512
+ case CRYPTO_SHA2_384_HMAC: return EVP_sha384();
+ case CRYPTO_SHA2_512_HMAC: return EVP_sha512();
+#endif
+ default:
+ printf("%s: failed to get an EVP, things will be broken!\n", __func__);
+ return NULL;
+ }
+}
+
+static int openssl_hmac(struct session_op *sess, struct crypt_op *cop)
+{
+ HMAC_CTX *ctx = ses_to_hmac(sess->ses);
+
+ if (!ctx) {
+ struct ctx_mapping *mapping = new_mapping();
+ if (!mapping) {
+ printf("%s: failed to get new mapping\n", __func__);
+ return 1;
+ }
+
+ mapping->ses = sess->ses;
+ mapping->type = ctx_type_hmac;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ ctx = mapping->ctx.hmac;
+
+ dbgp("calling HMAC_CTX_new");
+ ctx = HMAC_CTX_new();
+#else
+ ctx = &mapping->ctx.hmac;
+
+ dbgp("calling HMAC_CTX_init");
+ HMAC_CTX_init(ctx);
+#endif
+ dbgp("calling HMAC_Init_ex");
+ if (!HMAC_Init_ex(ctx, sess->mackey, sess->mackeylen,
+ sess_to_evp_md(sess), NULL)) {
+ printf("%s: HMAC_Init_ex failed\n", __func__);
+ return 1;
+ }
+ }
+
+ if (cop->len) {
+ dbgp("calling HMAC_Update");
+ if (!HMAC_Update(ctx, cop->src, cop->len)) {
+ printf("%s: HMAC_Update failed\n", __func__);
+ return 1;
+ }
+ }
+ if (cop->flags & COP_FLAG_FINAL ||
+ (cop->len && !(cop->flags & COP_FLAG_UPDATE))) {
+ dbgp("calling HMAC_Final");
+ if (!HMAC_Final(ctx, cop->mac, 0)) {
+ printf("%s: HMAC_Final failed\n", __func__);
+ remove_mapping(sess->ses);
+ return 1;
+ }
+ remove_mapping(sess->ses);
+ }
+ return 0;
+}
+
+static int openssl_md(struct session_op *sess, struct crypt_op *cop)
+{
+ EVP_MD_CTX *ctx = ses_to_md(sess->ses);
+
+ if (!ctx) {
+ struct ctx_mapping *mapping = new_mapping();
+ if (!mapping) {
+ printf("%s: failed to get new mapping\n", __func__);
+ return 1;
+ }
+
+ mapping->ses = sess->ses;
+ mapping->type = ctx_type_md;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ ctx = mapping->ctx.md;
+
+ dbgp("calling EVP_MD_CTX_new");
+ ctx = EVP_MD_CTX_new();
+#else
+ ctx = &mapping->ctx.md;
+
+ dbgp("calling EVP_MD_CTX_init");
+ EVP_MD_CTX_init(ctx);
+#endif
+ dbgp("calling EVP_DigestInit");
+ EVP_DigestInit(ctx, sess_to_evp_md(sess));
+ }
+
+ if (cop->len) {
+ dbgp("calling EVP_DigestUpdate");
+ EVP_DigestUpdate(ctx, cop->src, cop->len);
+ }
+ if (cop->flags & COP_FLAG_FINAL ||
+ (cop->len && !(cop->flags & COP_FLAG_UPDATE))) {
+ dbgp("calling EVP_DigestFinal");
+ EVP_DigestFinal(ctx, cop->mac, 0);
+ remove_mapping(sess->ses);
+ }
+
+ return 0;
+}
+
+static int openssl_aes(struct session_op *sess, struct crypt_op *cop)
+{
+ AES_KEY key;
+ int i, enc;
+ unsigned char ivec[AES_BLOCK_SIZE];
+
+ if (cop->len % AES_BLOCK_SIZE) {
+ printf("%s: illegal length passed, "
+ "not a multiple of AES_BLOCK_SIZE\n", __func__);
+ return 1;
+ }
+
+ switch (cop->op) {
+ case COP_ENCRYPT:
+ AES_set_encrypt_key(sess->key, sess->keylen * 8, &key);
+ enc = 1;
+ break;
+ case COP_DECRYPT:
+ AES_set_decrypt_key(sess->key, sess->keylen * 8, &key);
+ enc = 0;
+ break;
+ default:
+ printf("%s: unknown cop->op received!\n", __func__);
+ return 1;
+ }
+
+ switch (sess->cipher) {
+ case CRYPTO_AES_CBC:
+ memcpy(ivec, cop->iv, AES_BLOCK_SIZE);
+ AES_cbc_encrypt(cop->src, cop->dst, cop->len, &key, ivec, enc);
+ if (cop->flags & COP_FLAG_WRITE_IV)
+ memcpy(cop->iv, ivec, AES_BLOCK_SIZE);
+ break;
+#if 0
+ /* XXX: TODO: implement this stuff */
+ case CRYPTO_AES_CTR:
+ AES_ctr128_encrypt(cop->src, cop->dst, &key, cop->iv,
+ case CRYPTO_AES_XTS:
+#endif
+ case CRYPTO_AES_ECB:
+ for (i = 0; i < cop->len; i += AES_BLOCK_SIZE)
+ AES_ecb_encrypt(cop->src + i, cop->dst + i, &key, enc);
+ break;
+ }
+ return 0;
+}
+
+int openssl_cioccrypt(struct session_op *sess, struct crypt_op *cop)
+{
+ if (sess->mac && sess->mackey && sess->mackeylen)
+ openssl_hmac(sess, cop);
+ else if (sess->mac)
+ openssl_md(sess, cop);
+
+ switch (sess->cipher) {
+ case CRYPTO_AES_CBC:
+ case CRYPTO_AES_CTR:
+ case CRYPTO_AES_XTS:
+ case CRYPTO_AES_ECB:
+ openssl_aes(sess, cop);
+ break;
+ case 0:
+ /* no encryption wanted, everythings fine */
+ break;
+ default:
+ printf("%s: unknown cipher passed!\n", __func__);
+ break;
+ }
+
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/openssl_wrapper.h b/drivers/cryptodev-linux-master/tests/openssl_wrapper.h
new file mode 100644
index 00000000..5f1f5162
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/openssl_wrapper.h
@@ -0,0 +1,6 @@
+#ifndef __OPENSSL_WRAPPER_H
+#define __OPENSSL_WRAPPER_H
+
+int openssl_cioccrypt(struct session_op *, struct crypt_op *);
+
+#endif /* __OPENSSL_WRAPPER_H */
diff --git a/drivers/cryptodev-linux-master/tests/sha_speed.c b/drivers/cryptodev-linux-master/tests/sha_speed.c
new file mode 100644
index 00000000..1e672603
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/sha_speed.c
@@ -0,0 +1,198 @@
+/* sha_speed - simple SHA benchmark tool for cryptodev
+ *
+ * Copyright (C) 2011 by Phil Sutter <phil.sutter@viprinet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <crypto/cryptodev.h>
+
+static double udifftimeval(struct timeval start, struct timeval end)
+{
+ return (double)(end.tv_usec - start.tv_usec) +
+ (double)(end.tv_sec - start.tv_sec) * 1000 * 1000;
+}
+
+static int must_finish = 0;
+
+static void alarm_handler(int signo)
+{
+ must_finish = 1;
+}
+
+static char *units[] = { "", "Ki", "Mi", "Gi", "Ti", 0};
+static char *si_units[] = { "", "K", "M", "G", "T", 0};
+
+static void value2human(int si, double bytes, double time, double* data, double* speed,char* metric)
+{
+ int unit = 0;
+
+ *data = bytes;
+
+ if (si) {
+ while (*data > 1000 && si_units[unit + 1]) {
+ *data /= 1000;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", si_units[unit]);
+ } else {
+ while (*data > 1024 && units[unit + 1]) {
+ *data /= 1024;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", units[unit]);
+ }
+}
+
+
+int hash_data(struct session_op *sess, int fdc, int chunksize, int alignmask)
+{
+ struct crypt_op cop;
+ char *buffer;
+ static int val = 23;
+ struct timeval start, end;
+ double total = 0;
+ double secs, ddata, dspeed;
+ char metric[16];
+ uint8_t mac[AALG_MAX_RESULT_LEN];
+
+ if (alignmask) {
+ if (posix_memalign((void **)&buffer, alignmask + 1, chunksize)) {
+ printf("posix_memalign() failed!\n");
+ return 1;
+ }
+ } else {
+ if (!(buffer = malloc(chunksize))) {
+ perror("malloc()");
+ return 1;
+ }
+ }
+
+ printf("\tEncrypting in chunks of %d bytes: ", chunksize);
+ fflush(stdout);
+
+ memset(buffer, val++, chunksize);
+
+ must_finish = 0;
+ alarm(5);
+
+ gettimeofday(&start, NULL);
+ do {
+ memset(&cop, 0, sizeof(cop));
+ cop.ses = sess->ses;
+ cop.len = chunksize;
+ cop.op = COP_ENCRYPT;
+ cop.src = (unsigned char *)buffer;
+ cop.mac = mac;
+
+ if (ioctl(fdc, CIOCCRYPT, &cop)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+ total+=chunksize;
+ } while(must_finish==0);
+ gettimeofday(&end, NULL);
+
+ secs = udifftimeval(start, end)/ 1000000.0;
+
+ value2human(1, total, secs, &ddata, &dspeed, metric);
+ printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+
+ free(buffer);
+ return 0;
+}
+
+int main(void)
+{
+ int fd, i, fdc = -1, alignmask = 0;
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+
+ signal(SIGALRM, alarm_handler);
+
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+ perror("open()");
+ return 1;
+ }
+ if (ioctl(fd, CRIOGET, &fdc)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ fprintf(stderr, "Testing SHA1 Hash: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.mac = CRYPTO_SHA1;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ printf("requested hash CRYPTO_SHA1, got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ alignmask = siop.alignmask;
+#endif
+
+ for (i = 256; i <= (64 * 1024); i *= 4) {
+ if (hash_data(&sess, fdc, i, alignmask))
+ break;
+ }
+
+ fprintf(stderr, "\nTesting SHA256 Hash: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.mac = CRYPTO_SHA2_256;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ printf("requested hash CRYPTO_SHA2_256, got %s with driver %s\n",
+ siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
+ alignmask = siop.alignmask;
+#endif
+
+ for (i = 256; i <= (64 * 1024); i *= 4) {
+ if (hash_data(&sess, fdc, i, alignmask))
+ break;
+ }
+
+ close(fdc);
+ close(fd);
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/speed.c b/drivers/cryptodev-linux-master/tests/speed.c
new file mode 100644
index 00000000..951ae096
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/speed.c
@@ -0,0 +1,213 @@
+/* cryptodev_test - simple benchmark tool for cryptodev
+ *
+ * Copyright (C) 2010 by Phil Sutter <phil.sutter@viprinet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <crypto/cryptodev.h>
+
+static int si = 1; /* SI by default */
+
+static double udifftimeval(struct timeval start, struct timeval end)
+{
+ return (double)(end.tv_usec - start.tv_usec) +
+ (double)(end.tv_sec - start.tv_sec) * 1000 * 1000;
+}
+
+static volatile int must_finish;
+
+static void alarm_handler(int signo)
+{
+ must_finish = 1;
+}
+
+static char *units[] = { "", "Ki", "Mi", "Gi", "Ti", 0};
+static char *si_units[] = { "", "K", "M", "G", "T", 0};
+
+static void value2human(int si, double bytes, double time, double* data, double* speed,char* metric)
+{
+ int unit = 0;
+
+ *data = bytes;
+
+ if (si) {
+ while (*data > 1000 && si_units[unit + 1]) {
+ *data /= 1000;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", si_units[unit]);
+ } else {
+ while (*data > 1024 && units[unit + 1]) {
+ *data /= 1024;
+ unit++;
+ }
+ *speed = *data / time;
+ sprintf(metric, "%sB", units[unit]);
+ }
+}
+
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+int encrypt_data(struct session_op *sess, int fdc, int chunksize, int alignmask)
+{
+ struct crypt_op cop;
+ char *buffer, iv[32];
+ static int val = 23;
+ struct timeval start, end;
+ double total = 0;
+ double secs, ddata, dspeed;
+ char metric[16];
+
+ if (alignmask) {
+ if (posix_memalign((void **)&buffer, MAX(alignmask + 1, sizeof(void*)), chunksize)) {
+ printf("posix_memalign() failed! (mask %x, size: %d)\n", alignmask+1, chunksize);
+ return 1;
+ }
+ } else {
+ if (!(buffer = malloc(chunksize))) {
+ perror("malloc()");
+ return 1;
+ }
+ }
+
+ memset(iv, 0x23, 32);
+
+ printf("\tEncrypting in chunks of %d bytes: ", chunksize);
+ fflush(stdout);
+
+ memset(buffer, val++, chunksize);
+
+ must_finish = 0;
+ alarm(5);
+
+ gettimeofday(&start, NULL);
+ do {
+ memset(&cop, 0, sizeof(cop));
+ cop.ses = sess->ses;
+ cop.len = chunksize;
+ cop.iv = (unsigned char *)iv;
+ cop.op = COP_ENCRYPT;
+ cop.src = cop.dst = (unsigned char *)buffer;
+
+ if (ioctl(fdc, CIOCCRYPT, &cop)) {
+ perror("ioctl(CIOCCRYPT)");
+ return 1;
+ }
+ total+=chunksize;
+ } while(must_finish==0);
+ gettimeofday(&end, NULL);
+
+ secs = udifftimeval(start, end)/ 1000000.0;
+
+ value2human(si, total, secs, &ddata, &dspeed, metric);
+ printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs);
+ printf ("%.2f %s/sec\n", dspeed, metric);
+
+ free(buffer);
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ int fd, i, fdc = -1, alignmask = 0;
+ struct session_op sess;
+#ifdef CIOCGSESSINFO
+ struct session_info_op siop;
+#endif
+ char keybuf[32];
+
+ signal(SIGALRM, alarm_handler);
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
+ printf("Usage: speed [--kib]\n");
+ exit(0);
+ }
+ if (strcmp(argv[1], "--kib") == 0) {
+ si = 0;
+ }
+ }
+
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+ perror("open()");
+ return 1;
+ }
+ if (ioctl(fd, CRIOGET, &fdc)) {
+ perror("ioctl(CRIOGET)");
+ return 1;
+ }
+
+ fprintf(stderr, "Testing NULL cipher: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_NULL;
+ sess.keylen = 0;
+ sess.key = (unsigned char *)keybuf;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ alignmask = siop.alignmask;
+#endif
+
+ for (i = 512; i <= (64 * 1024); i *= 2) {
+ if (encrypt_data(&sess, fdc, i, alignmask))
+ break;
+ }
+
+ fprintf(stderr, "\nTesting AES-128-CBC cipher: \n");
+ memset(&sess, 0, sizeof(sess));
+ sess.cipher = CRYPTO_AES_CBC;
+ sess.keylen = 16;
+ memset(keybuf, 0x42, 16);
+ sess.key = (unsigned char *)keybuf;
+ if (ioctl(fdc, CIOCGSESSION, &sess)) {
+ perror("ioctl(CIOCGSESSION)");
+ return 1;
+ }
+#ifdef CIOCGSESSINFO
+ siop.ses = sess.ses;
+ if (ioctl(fdc, CIOCGSESSINFO, &siop)) {
+ perror("ioctl(CIOCGSESSINFO)");
+ return 1;
+ }
+ alignmask = siop.alignmask;
+#endif
+
+ for (i = 512; i <= (64 * 1024); i *= 2) {
+ if (encrypt_data(&sess, fdc, i, alignmask))
+ break;
+ }
+
+ close(fdc);
+ close(fd);
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/tests/testhelper.h b/drivers/cryptodev-linux-master/tests/testhelper.h
new file mode 100644
index 00000000..800d10db
--- /dev/null
+++ b/drivers/cryptodev-linux-master/tests/testhelper.h
@@ -0,0 +1,9 @@
+/*
+ * Some helper stuff shared between the sample programs.
+ */
+#ifndef __TESTHELPER_H
+#define __TESTHELPER_H
+
+#define buf_align(buf, align) (void *)(((unsigned long)(buf) + (align)) & ~(align))
+
+#endif /* __TESTHELPER_H */
diff --git a/drivers/cryptodev-linux-master/util.c b/drivers/cryptodev-linux-master/util.c
new file mode 100644
index 00000000..9eba4836
--- /dev/null
+++ b/drivers/cryptodev-linux-master/util.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 Maxim Levitsky
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <crypto/scatterwalk.h>
+#include <linux/scatterlist.h>
+#include "util.h"
+
+/* These were taken from Maxim Levitsky's patch to lkml.
+ */
+struct scatterlist *sg_advance(struct scatterlist *sg, int consumed)
+{
+ while (consumed >= sg->length) {
+ consumed -= sg->length;
+
+ sg = sg_next(sg);
+ if (!sg)
+ break;
+ }
+
+ WARN_ON(!sg && consumed);
+
+ if (!sg)
+ return NULL;
+
+ sg->offset += consumed;
+ sg->length -= consumed;
+
+ if (sg->offset >= PAGE_SIZE) {
+ struct page *page =
+ nth_page(sg_page(sg), sg->offset / PAGE_SIZE);
+ sg_set_page(sg, page, sg->length, sg->offset % PAGE_SIZE);
+ }
+
+ return sg;
+}
+
+/**
+ * sg_copy - copies sg entries from sg_from to sg_to, such
+ * as sg_to covers first 'len' bytes from sg_from.
+ */
+int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to, int len)
+{
+ while (len > sg_from->length) {
+ len -= sg_from->length;
+
+ sg_set_page(sg_to, sg_page(sg_from),
+ sg_from->length, sg_from->offset);
+
+ sg_to = sg_next(sg_to);
+ sg_from = sg_next(sg_from);
+
+ if (len && (!sg_from || !sg_to))
+ return -ENOMEM;
+ }
+
+ if (len)
+ sg_set_page(sg_to, sg_page(sg_from),
+ len, sg_from->offset);
+ sg_mark_end(sg_to);
+ return 0;
+}
+
diff --git a/drivers/cryptodev-linux-master/util.h b/drivers/cryptodev-linux-master/util.h
new file mode 100644
index 00000000..204de758
--- /dev/null
+++ b/drivers/cryptodev-linux-master/util.h
@@ -0,0 +1,2 @@
+int sg_copy(struct scatterlist *sg_from, struct scatterlist *sg_to, int len);
+struct scatterlist *sg_advance(struct scatterlist *sg, int consumed);
diff --git a/drivers/cryptodev-linux-master/zc.c b/drivers/cryptodev-linux-master/zc.c
new file mode 100644
index 00000000..fdf7da17
--- /dev/null
+++ b/drivers/cryptodev-linux-master/zc.c
@@ -0,0 +1,235 @@
+/*
+ * Driver for /dev/crypto device (aka CryptoDev)
+ *
+ * Copyright (c) 2009-2013 Nikos Mavrogiannopoulos <nmav@gnutls.org>
+ * Copyright (c) 2010 Phil Sutter
+ * Copyright (c) 2011, 2012 OpenSSL Software Foundation, Inc.
+ *
+ * This file is part of linux cryptodev.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <crypto/hash.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/ioctl.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+#include <linux/pagemap.h>
+#include <linux/uaccess.h>
+#include <crypto/scatterwalk.h>
+#include <linux/scatterlist.h>
+#include "cryptodev_int.h"
+#include "zc.h"
+#include "version.h"
+
+/* Helper functions to assist zero copy.
+ * This needs to be redesigned and moved out of the session. --nmav
+ */
+
+/* offset of buf in it's first page */
+#define PAGEOFFSET(buf) ((unsigned long)buf & ~PAGE_MASK)
+
+/* fetch the pages addr resides in into pg and initialise sg with them */
+int __get_userbuf(uint8_t __user *addr, uint32_t len, int write,
+ unsigned int pgcount, struct page **pg, struct scatterlist *sg,
+ struct task_struct *task, struct mm_struct *mm)
+{
+ int ret, pglen, i = 0;
+ struct scatterlist *sgp;
+
+ if (unlikely(!pgcount || !len || !addr)) {
+ sg_mark_end(sg);
+ return 0;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0))
+ down_read(&mm->mmap_sem);
+#else
+ mmap_read_lock(mm);
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 168))
+ ret = get_user_pages(task, mm,
+ (unsigned long)addr, pgcount, write, 0, pg, NULL);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
+ ret = get_user_pages(task, mm,
+ (unsigned long)addr, pgcount, write, pg, NULL);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
+ ret = get_user_pages_remote(task, mm,
+ (unsigned long)addr, pgcount, write, 0, pg, NULL);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
+ ret = get_user_pages_remote(task, mm,
+ (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0,
+ pg, NULL);
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
+ ret = get_user_pages_remote(task, mm,
+ (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0,
+ pg, NULL, NULL);
+#else
+ ret = get_user_pages_remote(mm,
+ (unsigned long)addr, pgcount, write ? FOLL_WRITE : 0,
+ pg, NULL, NULL);
+#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0))
+ up_read(&mm->mmap_sem);
+#else
+ mmap_read_unlock(mm);
+#endif
+ if (ret != pgcount)
+ return -EINVAL;
+
+ sg_init_table(sg, pgcount);
+
+ pglen = min((ptrdiff_t)(PAGE_SIZE - PAGEOFFSET(addr)), (ptrdiff_t)len);
+ sg_set_page(sg, pg[i++], pglen, PAGEOFFSET(addr));
+
+ len -= pglen;
+ for (sgp = sg_next(sg); len; sgp = sg_next(sgp)) {
+ pglen = min((uint32_t)PAGE_SIZE, len);
+ sg_set_page(sgp, pg[i++], pglen, 0);
+ len -= pglen;
+ }
+ sg_mark_end(sg_last(sg, pgcount));
+ return 0;
+}
+
+int adjust_sg_array(struct csession *ses, int pagecount)
+{
+ struct scatterlist *sg;
+ struct page **pages;
+ int array_size;
+
+ for (array_size = ses->array_size; array_size < pagecount;
+ array_size *= 2)
+ ;
+ ddebug(0, "reallocating from %d to %d pages",
+ ses->array_size, array_size);
+ pages = krealloc(ses->pages, array_size * sizeof(struct page *),
+ GFP_KERNEL);
+ if (unlikely(!pages))
+ return -ENOMEM;
+ ses->pages = pages;
+ sg = krealloc(ses->sg, array_size * sizeof(struct scatterlist),
+ GFP_KERNEL);
+ if (unlikely(!sg))
+ return -ENOMEM;
+ ses->sg = sg;
+ ses->array_size = array_size;
+
+ return 0;
+}
+
+void release_user_pages(struct csession *ses)
+{
+ unsigned int i;
+
+ for (i = 0; i < ses->used_pages; i++) {
+ if (!PageReserved(ses->pages[i]))
+ SetPageDirty(ses->pages[i]);
+
+ if (ses->readonly_pages == 0)
+ flush_dcache_page(ses->pages[i]);
+ else
+ ses->readonly_pages--;
+
+ put_page(ses->pages[i]);
+ }
+ ses->used_pages = 0;
+}
+
+/* make src and dst available in scatterlists.
+ * dst might be the same as src.
+ */
+int get_userbuf(struct csession *ses,
+ void *__user src, unsigned int src_len,
+ void *__user dst, unsigned int dst_len,
+ struct task_struct *task, struct mm_struct *mm,
+ struct scatterlist **src_sg,
+ struct scatterlist **dst_sg)
+{
+ int src_pagecount, dst_pagecount;
+ int rc;
+
+ /* Empty input is a valid option to many algorithms & is tested by NIST/FIPS */
+ /* Make sure NULL input has 0 length */
+ if (!src && src_len)
+ src_len = 0;
+
+ /* I don't know that null output is ever useful, but we can handle it gracefully */
+ /* Make sure NULL output has 0 length */
+ if (!dst && dst_len)
+ dst_len = 0;
+
+ src_pagecount = PAGECOUNT(src, src_len);
+ dst_pagecount = PAGECOUNT(dst, dst_len);
+
+ ses->used_pages = (src == dst) ? max(src_pagecount, dst_pagecount)
+ : src_pagecount + dst_pagecount;
+
+ ses->readonly_pages = (src == dst) ? 0 : src_pagecount;
+
+ if (ses->used_pages > ses->array_size) {
+ rc = adjust_sg_array(ses, ses->used_pages);
+ if (rc)
+ return rc;
+ }
+
+ if (src == dst) { /* inplace operation */
+ /* When we encrypt for authenc modes we need to write
+ * more data than the ones we read. */
+ if (src_len < dst_len)
+ src_len = dst_len;
+ rc = __get_userbuf(src, src_len, 1, ses->used_pages,
+ ses->pages, ses->sg, task, mm);
+ if (unlikely(rc)) {
+ derr(1, "failed to get user pages for data IO");
+ return rc;
+ }
+ (*src_sg) = (*dst_sg) = ses->sg;
+ return 0;
+ }
+
+ *src_sg = NULL; /* default to no input */
+ *dst_sg = NULL; /* default to ignore output */
+
+ if (likely(src)) {
+ rc = __get_userbuf(src, src_len, 0, ses->readonly_pages,
+ ses->pages, ses->sg, task, mm);
+ if (unlikely(rc)) {
+ derr(1, "failed to get user pages for data input");
+ return rc;
+ }
+ *src_sg = ses->sg;
+ }
+
+ if (likely(dst)) {
+ const unsigned int writable_pages =
+ ses->used_pages - ses->readonly_pages;
+ struct page **dst_pages = ses->pages + ses->readonly_pages;
+ *dst_sg = ses->sg + ses->readonly_pages;
+
+ rc = __get_userbuf(dst, dst_len, 1, writable_pages,
+ dst_pages, *dst_sg, task, mm);
+ if (unlikely(rc)) {
+ derr(1, "failed to get user pages for data output");
+ release_user_pages(ses); /* FIXME: use __release_userbuf(src, ...) */
+ return rc;
+ }
+ }
+ return 0;
+}
diff --git a/drivers/cryptodev-linux-master/zc.h b/drivers/cryptodev-linux-master/zc.h
new file mode 100644
index 00000000..666c4a54
--- /dev/null
+++ b/drivers/cryptodev-linux-master/zc.h
@@ -0,0 +1,25 @@
+#ifndef ZC_H
+# define ZC_H
+
+/* For zero copy */
+int __get_userbuf(uint8_t __user *addr, uint32_t len, int write,
+ unsigned int pgcount, struct page **pg, struct scatterlist *sg,
+ struct task_struct *task, struct mm_struct *mm);
+void release_user_pages(struct csession *ses);
+
+int get_userbuf(struct csession *ses,
+ void *__user src, unsigned int src_len,
+ void *__user dst, unsigned int dst_len,
+ struct task_struct *task, struct mm_struct *mm,
+ struct scatterlist **src_sg,
+ struct scatterlist **dst_sg);
+
+/* buflen ? (last page - first page + 1) : 0 */
+#define PAGECOUNT(buf, buflen) ((buflen) \
+ ? ((((unsigned long)(buf + buflen - 1)) >> PAGE_SHIFT) - \
+ (((unsigned long)(buf )) >> PAGE_SHIFT) + 1) \
+ : 0)
+
+#define DEFAULT_PREALLOC_PAGES 32
+
+#endif
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 141aefbe..1a69fb51 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -75,6 +75,61 @@ config AMCC_PPC440SPE_ADMA
help
Enable support for the AMCC PPC440SPe RAID engines.
+config DW_DMAC
+ tristate "Synopsys DesignWare AHB DMA support"
+ depends on HAVE_CLK
+ select DMA_ENGINE
+ default y if CPU_AT32AP7000
+ help
+ Support the Synopsys DesignWare AHB DMA controller. This
+ can be integrated in chips such as the Atmel AT32ap7000.
+
+config CHANNEL_ALLOC_MEM_CLASSICS
+ bool "chose malloc desc with classics, not from dma pool"
+ help
+ the pool size default is 256KB.
+ default y
+
+config FH_DMAC
+ tristate "FH DesignWare AHB DMA support"
+ depends on HAVE_CLK
+ select CHANNEL_ALLOC_MEM_CLASSICS
+ select DMA_ENGINE
+
+ help
+ Support the Synopsys DesignWare AHB DMA controller. This
+ can be integrated in chips such as the FullHan.
+
+
+if !FH_DMAC
+ config FH_AXI_DMAC
+ tristate "FH DesignWare AXI DMA support"
+ depends on HAVE_CLK
+ select CHANNEL_ALLOC_MEM_CLASSICS
+ select DMA_ENGINE
+
+ help
+ Support the Synopsys DesignWare AHB DMA controller. This
+ can be integrated in chips such as the FullHan.
+endif
+
+if FH_DMAC || FH_AXI_DMAC
+
+config FH_DMAC_MISC
+ bool "FH DMAC Misc Device Enable"
+ default y
+ help
+ FH DMAC Misc Device Enable
+
+menu "dma tinyconfig"
+
+config CHANNEL_ALLOC_DESC_NUM
+ int "CHANNEL_ALLOC_DESC_NUM"
+ default 256
+endmenu
+
+endif
+
config AT_HDMAC
tristate "Atmel AHB DMA support"
depends on ARCH_AT91
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index e4dc9cac..a0a28152 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -67,6 +67,8 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o
obj-$(CONFIG_TI_EDMA) += edma.o
obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
obj-$(CONFIG_ZX_DMA) += zx296702_dma.o
+obj-$(CONFIG_FH_DMAC) += fh_dmac.o
+obj-$(CONFIG_FH_AXI_DMAC) += fh_axi_dma_driver.o fh_axi_dma_adapt.o
obj-y += qcom/
obj-y += xilinx/
diff --git a/drivers/dma/fh_axi_dma_adapt.c b/drivers/dma/fh_axi_dma_adapt.c
new file mode 100644
index 00000000..14f3f4f8
--- /dev/null
+++ b/drivers/dma/fh_axi_dma_adapt.c
@@ -0,0 +1,829 @@
+#include "fh_axi_dma_adapt.h"
+
+static inline struct fh_axi_dma_adapt *to_fh_axi_dma(struct dma_device *ddev);
+static inline struct fh_axi_dma_channel_adapt *to_fh_axi_dma_chan(struct dma_chan *chan);
+static dma_cookie_t fh_axi_dma_adapt_submit(struct dma_async_tx_descriptor *tx);
+static int adapt_alloc_chan_resources(struct dma_chan *chan);
+static void adapt_free_chan_resources(struct dma_chan *chan);
+static FH_UINT32 cal_data_width(dma_addr_t dest, dma_addr_t src, size_t len);
+static void adapt_prep_callback(void *p);
+static struct dma_async_tx_descriptor *adapt_prep_dma_memcpy(struct dma_chan *chan,
+dma_addr_t dest, dma_addr_t src, size_t len, unsigned long flags);
+static FH_UINT32 width_from_core_to_driver(FH_UINT32 core_width);
+static FH_UINT32 burst_from_core_to_driver(FH_UINT32 core_width);
+
+static struct dma_async_tx_descriptor *
+adapt_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context);
+
+static int adapt_device_config(struct dma_chan *chan, struct dma_slave_config *config);
+static int adapt_device_pause(struct dma_chan *chan);
+static int adapt_device_resume(struct dma_chan *chan);
+
+static enum dma_status
+adapt_tx_status(struct dma_chan *chan,
+dma_cookie_t cookie, struct dma_tx_state *txstate);
+
+static irqreturn_t adapt_dma_interrupt(int irq, void *dev_id);
+static void adapt_axi_dma_tasklet(unsigned long data);
+static struct fh_axi_dma * adapt_to_driver_handle(struct fh_axi_dma_adapt *p_adapt);
+static void adapt_device_issue_pending(struct dma_chan *chan);
+static int adapt_device_terminate_all(struct dma_chan *chan);
+static int fh_axi_dma_adapt_probe(struct platform_device *pdev);
+static int fh_axi_dma_adapt_remove(struct platform_device *pdev);
+static int __init fh_axi_dma_adapt_init(void);
+static void __exit fh_axi_dma_adapt_exit(void);
+
+static inline struct fh_axi_dma_adapt *to_fh_axi_dma(struct dma_device *ddev)
+{
+ return container_of(ddev, struct fh_axi_dma_adapt, dma);
+}
+
+static inline struct fh_axi_dma_channel_adapt *to_fh_axi_dma_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct fh_axi_dma_channel_adapt, core_chan);
+}
+
+static struct fh_axi_dma * adapt_to_driver_handle(struct fh_axi_dma_adapt *p_adapt)
+{
+ return p_adapt->driver_pri;
+}
+
+static void fh_axi_adapt_isr_prep_func_callback(void *p)
+{
+ dma_cookie_complete((struct dma_async_tx_descriptor *)p);
+}
+
+static dma_cookie_t fh_axi_dma_adapt_submit(struct dma_async_tx_descriptor *tx)
+{
+ dma_cookie_t cookie;
+ struct axi_dma_ops *p_ops;
+ struct dma_transfer *p_trans;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct dma_chan *chan = tx->chan;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ cookie = dma_cookie_assign(tx);
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ p_trans->isr_prepare_callback = fh_axi_adapt_isr_prep_func_callback;
+ p_trans->isr_prepare_para = (void *)tx;
+ p_trans->complete_callback = tx->callback;
+ p_trans->complete_para = tx->callback_param;
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_SINGLE_TRANSFER, p_trans);
+ return cookie;
+}
+
+
+static int adapt_alloc_chan_resources(struct dma_chan *chan)
+{
+
+ struct axi_dma_ops *p_ops;
+ struct dma_transfer *p_trans;
+ int i;
+ struct dma_async_tx_descriptor *p_async;
+ FH_UINT32 desc_no;
+ FH_UINT32 each_desc_size;
+ FH_UINT32 driver_desc_phy_base;
+ FH_UINT32 desc_cap;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ dma_cookie_init(chan);
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_trans->dma_number = fhd->dma.dev_id;
+ p_trans->channel_number = chan->chan_id;
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_REQUEST_CHANNEL, p_trans);
+ p_ops->axi_dma_get_desc_para(fhd->driver_pri, p_trans, &desc_no, &driver_desc_phy_base, &each_desc_size, &desc_cap);
+ fhc_adapt->ch_adapt_desc_base = (struct dma_async_tx_descriptor *)devm_kzalloc(&fhd->pdev->dev,
+ sizeof(struct dma_async_tx_descriptor) * desc_no, GFP_KERNEL);
+ for(i = 0, p_async = fhc_adapt->ch_adapt_desc_base; i < desc_no; i++, p_async++){
+ dma_async_tx_descriptor_init(p_async, chan);
+ p_async->tx_submit = fh_axi_dma_adapt_submit;
+ p_async->flags = DMA_CTRL_ACK;
+ p_async->phys = driver_desc_phy_base + (i * each_desc_size);
+ }
+
+ return desc_no;
+}
+
+
+static void adapt_free_chan_resources(struct dma_chan *chan)
+{
+ struct axi_dma_ops *p_ops;
+ struct dma_transfer *p_trans;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_RELEASE_CHANNEL, p_trans);
+ if(fhc_adapt->ch_adapt_desc_base)
+ devm_kfree(&fhd->pdev->dev, fhc_adapt->ch_adapt_desc_base);
+}
+
+static FH_UINT32 cal_data_width(dma_addr_t dest, dma_addr_t src, size_t len)
+{
+ FH_UINT32 data_width = 0;
+
+ if (!((src % 4) || (dest % 4) || (len % 4)))
+ data_width = DW_DMA_SLAVE_WIDTH_32BIT;
+ else if (!((src % 2) || (dest % 2) || (len % 2)))
+ data_width = DW_DMA_SLAVE_WIDTH_16BIT;
+ else
+ data_width = DW_DMA_SLAVE_WIDTH_8BIT;
+
+ return data_width;
+}
+
+static void adapt_prep_callback(void *p)
+{
+ struct dma_chan *chan = (struct dma_chan *)p;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ devm_kfree(&fhd->pdev->dev, fhc_adapt->desc_head);
+}
+
+
+static struct dma_async_tx_descriptor *
+adapt_prep_dma_memcpy(struct dma_chan *chan,
+dma_addr_t dest, dma_addr_t src,
+size_t len, unsigned long flags)
+{
+ struct axi_dma_ops *p_ops;
+ struct dma_transfer *p_trans;
+ int i;
+ FH_UINT32 desc_no;
+ FH_UINT32 each_desc_size;
+ FH_UINT32 driver_desc_phy_base;
+ FH_UINT32 width;
+ FH_UINT32 ot_len;
+ FH_UINT32 need_trans_size;
+ FH_UINT32 desc_cap;
+ struct dma_transfer_desc *p_desc;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_trans = &fhc_adapt->trans;
+ width = cal_data_width(dest, src, len);
+
+ p_ops->axi_dma_get_desc_para(fhd->driver_pri, p_trans, &desc_no, &driver_desc_phy_base, &each_desc_size, &desc_cap);
+
+ //cal size with width
+ len = len / ( 1 << width );
+ need_trans_size = len / desc_cap;
+ if(len % desc_cap)
+ need_trans_size++;
+
+ fhc_adapt->desc_size = need_trans_size;
+ fhc_adapt->desc_head = devm_kzalloc(&fhd->pdev->dev,
+ sizeof(struct dma_transfer_desc) * need_trans_size, GFP_KERNEL);
+
+ BUG_ON(!fhc_adapt->desc_head);
+ p_desc = fhc_adapt->desc_head;
+
+ p_trans->fc_mode = DMA_M2M;
+ i = 0;
+ while(len != 0){
+ ot_len = min_t(unsigned int, desc_cap, len);
+ p_desc->src_add = src + i * desc_cap * (1 << width);
+ p_desc->src_width = width;
+ p_desc->src_msize = DW_DMA_SLAVE_MSIZE_32;
+ p_desc->src_inc_mode = DW_DMA_SLAVE_INC;
+
+ p_desc->dst_add = dest + i * desc_cap * (1 << width);
+ p_desc->dst_width = width;
+ p_desc->dst_msize = DW_DMA_SLAVE_MSIZE_32;
+ p_desc->dst_inc_mode = DW_DMA_SLAVE_INC;
+ p_desc->size = ot_len;
+ p_desc++;
+ i++;
+ len -= ot_len;
+ }
+ p_trans->p_desc = fhc_adapt->desc_head;
+ p_trans->desc_size = need_trans_size;
+
+ p_trans->prepare_callback = adapt_prep_callback;
+ p_trans->prepare_para = chan;
+
+ return fhc_adapt->ch_adapt_desc_base;
+}
+
+
+static FH_UINT32 width_from_core_to_driver(FH_UINT32 core_width)
+{
+ FH_UINT32 ret;
+
+ switch(core_width){
+ case DMA_SLAVE_BUSWIDTH_1_BYTE :
+ ret = DW_DMA_SLAVE_WIDTH_8BIT;
+ break;
+
+ case DMA_SLAVE_BUSWIDTH_2_BYTES :
+ ret = DW_DMA_SLAVE_WIDTH_16BIT;
+ break;
+
+ case DMA_SLAVE_BUSWIDTH_4_BYTES :
+ ret = DW_DMA_SLAVE_WIDTH_32BIT;
+ break;
+
+ default :
+ BUG_ON(1);
+ }
+ return ret;
+}
+
+
+static FH_UINT32 burst_from_core_to_driver(FH_UINT32 core_width)
+{
+ FH_UINT32 ret;
+ switch(core_width){
+ case 1 :
+ ret = DW_DMA_SLAVE_MSIZE_1;
+ break;
+
+ case 4 :
+ ret = DW_DMA_SLAVE_MSIZE_4;
+ break;
+
+ case 8 :
+ ret = DW_DMA_SLAVE_MSIZE_8;
+ break;
+
+ case 16 :
+ ret = DW_DMA_SLAVE_MSIZE_16;
+ break;
+
+ case 32 :
+ ret = DW_DMA_SLAVE_MSIZE_32;
+ break;
+
+ default :
+ BUG_ON(1);
+ }
+ return ret;
+}
+
+
+static struct dma_async_tx_descriptor *
+adapt_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+
+ struct dma_transfer *p_trans;
+ int i;
+ struct scatterlist *sg;
+ FH_UINT32 dev_width, dev_add;
+ FH_UINT32 mem_width, mem_add;
+ FH_UINT32 ot_len;
+ struct fh_dma_extra *ext_para = (struct fh_dma_extra *)context;
+ struct dma_slave_config *sconfig;
+ struct dma_transfer_desc *p_desc;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ fhc_adapt->desc_size = sg_len;
+
+ fhc_adapt->desc_head = devm_kzalloc(&fhd->pdev->dev,
+ sizeof(struct dma_transfer_desc) * sg_len, GFP_KERNEL);
+ BUG_ON(!fhc_adapt->desc_head);
+ p_desc = fhc_adapt->desc_head;
+ sconfig = &fhc_adapt->sconfig;
+
+ if (ext_para)
+ memcpy(&fhc_adapt->ext_para, ext_para, sizeof(struct fh_dma_extra));
+
+
+ switch (direction) {
+ case DMA_MEM_TO_DEV:
+ p_trans->fc_mode = DMA_M2P;
+ p_trans->dst_per = sconfig->slave_id;
+ dev_width = width_from_core_to_driver(sconfig->dst_addr_width);
+ dev_add = sconfig->dst_addr;
+ mem_width = width_from_core_to_driver(sconfig->src_addr_width);
+
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ mem_add = sg_dma_address(sg);
+ ot_len = sg_dma_len(sg);
+ p_desc->src_add = mem_add;
+ p_desc->src_width = mem_width;
+ ot_len = ot_len >> p_desc->src_width;
+ p_desc->src_msize = burst_from_core_to_driver(sconfig->src_maxburst);
+ p_desc->src_inc_mode = DW_DMA_SLAVE_INC;
+ p_desc->dst_add = dev_add;
+ p_desc->dst_width = dev_width;
+ p_desc->dst_msize = burst_from_core_to_driver(sconfig->dst_maxburst);
+ p_desc->dst_inc_mode = DW_DMA_SLAVE_FIX;
+ if (ext_para){
+ p_desc->dst_inc_mode = ext_para->dinc;
+ }
+ p_desc->size = ot_len;
+ p_desc++;
+ }
+ break;
+
+ case DMA_DEV_TO_MEM:
+ p_trans->fc_mode = DMA_P2M;
+ p_trans->src_per = sconfig->slave_id;
+ dev_width = width_from_core_to_driver(sconfig->src_addr_width);
+ dev_add = sconfig->src_addr;
+ mem_width = width_from_core_to_driver(sconfig->dst_addr_width);
+
+ for_each_sg(sgl, sg, sg_len, i) {
+ mem_add = sg_dma_address(sg);
+ ot_len = sg_dma_len(sg);
+
+ p_desc->src_add = dev_add;
+ p_desc->src_width = dev_width;
+ ot_len = ot_len >> p_desc->src_width;
+ p_desc->src_msize = burst_from_core_to_driver(sconfig->src_maxburst);
+ p_desc->src_inc_mode = DW_DMA_SLAVE_FIX;
+ if (ext_para)
+ p_desc->src_inc_mode = ext_para->sinc;
+ p_desc->dst_add = mem_add;
+ p_desc->dst_width = mem_width;
+ p_desc->dst_msize = burst_from_core_to_driver(sconfig->dst_maxburst);
+ p_desc->dst_inc_mode = DW_DMA_SLAVE_INC;
+ p_desc->size = ot_len;
+
+ p_desc++;
+ }
+
+ break;
+
+ default:
+ return NULL;
+ }
+ p_trans->p_desc = fhc_adapt->desc_head;
+ p_trans->desc_size = fhc_adapt->desc_size;
+ p_trans->prepare_callback = adapt_prep_callback;
+ p_trans->prepare_para = chan;
+
+ return fhc_adapt->ch_adapt_desc_base;
+}
+
+
+static int adapt_device_config(struct dma_chan *chan, struct dma_slave_config *config)
+{
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ memcpy(&fhc_adapt->sconfig, config, sizeof(struct dma_slave_config));
+ return 0;
+}
+
+
+static int adapt_device_pause(struct dma_chan *chan)
+{
+ struct axi_dma_ops *p_ops;
+ struct dma_transfer *p_trans;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_PAUSE, p_trans);
+
+
+ return 0;
+}
+
+static int adapt_device_resume(struct dma_chan *chan)
+{
+ struct axi_dma_ops *p_ops;
+ struct dma_transfer *p_trans;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_RESUME, p_trans);
+
+
+ return 0;
+}
+
+
+
+static enum dma_status
+adapt_tx_status(struct dma_chan *chan,
+dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+ enum dma_status ret;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ return ret;
+}
+
+
+static irqreturn_t adapt_dma_interrupt(int irq, void *dev_id)
+{
+ struct fh_axi_dma_adapt *fh_axi_adapt_obj;
+ struct axi_dma_ops *p_ops;
+ struct fh_axi_dma *p_driver_handle;
+
+ fh_axi_adapt_obj = (struct fh_axi_dma_adapt *)dev_id;
+ p_driver_handle = adapt_to_driver_handle(fh_axi_adapt_obj);
+ p_ops = get_fh_axi_dma_ops(p_driver_handle);
+ // close dma isr .tasklet will reopen
+ p_ops->axi_dma_isr_enable_set(p_driver_handle, DMA_COMMON_ISR_CLOSE);
+ tasklet_schedule(&fh_axi_adapt_obj->tasklet);
+
+ return IRQ_HANDLED;
+}
+
+
+static void adapt_axi_dma_tasklet(unsigned long data)
+{
+ struct axi_dma_ops *p_ops;
+ struct fh_axi_dma *p_driver_handle;
+ struct fh_axi_dma_adapt *p_adapt = (struct fh_axi_dma_adapt *)data;
+
+ p_driver_handle = adapt_to_driver_handle(p_adapt);
+ p_ops = get_fh_axi_dma_ops(p_driver_handle);
+ p_ops->axi_dma_isr_process(p_driver_handle);
+ p_ops->axi_dma_isr_enable_set(p_driver_handle, DMA_COMMON_ISR_OPEN);
+}
+
+/****
+ *
+ * adapt cyclic
+ *
+****/
+
+inline dma_addr_t fh_dma_get_src_addr(struct dma_chan *chan)
+{
+ struct dma_transfer *p_trans;
+ struct axi_dma_ops * p_ops;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ return (dma_addr_t)p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_GET_SAR, p_trans);
+
+}
+EXPORT_SYMBOL(fh_dma_get_src_addr);
+
+inline dma_addr_t fh_dma_get_dst_addr(struct dma_chan *chan)
+{
+ struct dma_transfer *p_trans;
+ struct axi_dma_ops * p_ops;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ return (dma_addr_t)p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_GET_DAR, p_trans);
+}
+EXPORT_SYMBOL(fh_dma_get_dst_addr);
+
+
+int fh_dma_cyclic_start(struct dma_chan *chan)
+{
+ struct dma_transfer *p_trans;
+ struct axi_dma_ops * p_ops;
+ struct fh_cyclic_desc *p_cyclic;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_cyclic = &fhc_adapt->cyclic;
+ p_trans = &fhc_adapt->trans;
+
+ p_trans->complete_callback = p_cyclic->period_callback;
+ p_trans->complete_para = p_cyclic->period_callback_param;
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_CYCLIC_START, p_trans);
+
+ return 0;
+}
+EXPORT_SYMBOL(fh_dma_cyclic_start);
+
+
+void fh_dma_cyclic_stop(struct dma_chan *chan)
+{
+ struct dma_transfer *p_trans;
+ struct axi_dma_ops * p_ops;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_CYCLIC_STOP, p_trans);
+}
+EXPORT_SYMBOL(fh_dma_cyclic_stop);
+
+
+struct fh_cyclic_desc *fh_dma_cyclic_prep(struct dma_chan *chan,
+ dma_addr_t buf_addr, size_t buf_len, size_t period_len,
+ enum dma_transfer_direction direction)
+{
+ struct dma_transfer *p_trans;
+ int i;
+ FH_UINT32 ot_len;
+ FH_UINT32 periods;
+ struct axi_dma_ops * p_ops;
+ struct fh_dma_slave *fhs = chan->private;
+ struct dma_transfer_desc *p_desc;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+ periods = buf_len / period_len;
+ fhc_adapt->desc_size = periods;
+ fhc_adapt->desc_head = devm_kzalloc(&fhd->pdev->dev,
+ sizeof(struct dma_transfer_desc) * periods, GFP_KERNEL);
+
+ BUG_ON(!fhc_adapt->desc_head);
+ p_desc = fhc_adapt->desc_head;
+
+ switch (direction) {
+ case DMA_MEM_TO_DEV:
+ p_trans->fc_mode = DMA_M2P;
+ p_trans->dst_per = fhs->cfg_hi;
+ for (i = 0; i < periods; i++){
+ p_desc->src_add = buf_addr + (period_len * i);
+ p_desc->src_width = DW_DMA_SLAVE_WIDTH_32BIT;
+ ot_len = period_len >> p_desc->src_width;
+ p_desc->src_msize = fhs->src_msize;
+ p_desc->src_inc_mode = DW_DMA_SLAVE_INC;
+
+ p_desc->dst_add = fhs->tx_reg;
+ p_desc->dst_width = fhs->reg_width;
+ p_desc->dst_msize = fhs->dst_msize;
+ p_desc->dst_inc_mode = DW_DMA_SLAVE_FIX;
+ p_desc->size = ot_len;
+ p_desc++;
+ }
+ break;
+
+ case DMA_DEV_TO_MEM:
+
+ p_trans->fc_mode = DMA_P2M;
+ p_trans->src_per = fhs->cfg_hi;
+
+ for (i = 0; i < periods; i++){
+ p_desc->src_add = fhs->rx_reg;
+ p_desc->src_width = fhs->reg_width;
+ ot_len = period_len >> p_desc->src_width;
+ p_desc->src_msize = fhs->src_msize;
+ p_desc->src_inc_mode = DW_DMA_SLAVE_FIX;
+
+ p_desc->dst_add = buf_addr + (period_len * i);
+ p_desc->dst_width = DW_DMA_SLAVE_WIDTH_32BIT;
+ p_desc->dst_msize = fhs->dst_msize;
+ p_desc->dst_inc_mode = DW_DMA_SLAVE_INC;
+ p_desc->size = ot_len;
+ p_desc++;
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ p_trans->p_desc = fhc_adapt->desc_head;
+ p_trans->desc_size = fhc_adapt->desc_size;
+ p_trans->prepare_callback = adapt_prep_callback;
+ p_trans->cyclic_periods = periods;
+ p_trans->prepare_para = chan;
+ p_ops = get_fh_axi_dma_ops(fhd->driver_pri);
+ p_ops->axi_dma_control(fhd->driver_pri, AXI_DMA_CTRL_DMA_CYCLIC_PREPARE, p_trans);
+
+ return &fhc_adapt->cyclic;
+
+}
+EXPORT_SYMBOL(fh_dma_cyclic_prep);
+
+
+
+void fh_dma_cyclic_free(struct dma_chan *chan)
+{
+
+ struct dma_transfer *p_trans;
+ struct fh_axi_dma_channel_adapt *fhc_adapt;
+ struct fh_axi_dma_adapt *fhd = to_fh_axi_dma(chan->device);
+ fhc_adapt = to_fh_axi_dma_chan(chan);
+ p_trans = &fhc_adapt->trans;
+
+ if(fhc_adapt->ch_adapt_desc_base)
+ devm_kfree(&fhd->pdev->dev, fhc_adapt->ch_adapt_desc_base);
+}
+EXPORT_SYMBOL(fh_dma_cyclic_free);
+
+
+static void adapt_device_issue_pending(struct dma_chan *chan)
+{
+
+}
+
+static int adapt_device_terminate_all(struct dma_chan *chan)
+{
+ return 0;
+}
+
+static void adapt_plat_info_get(struct fh_axi_dma_platform_data *p_info,
+struct platform_device *pdev){
+#ifndef CONFIG_OF
+ /* just cpy plat data.*/
+ memcpy((void *)p_info, (void *)pdev->dev.platform_data,
+ sizeof(struct fh_axi_dma_platform_data));
+#endif
+}
+
+
+static int fh_axi_dma_adapt_probe(struct platform_device *pdev)
+{
+ struct fh_axi_dma_platform_data p_axi_plat;
+ struct dma_transfer trans;
+ size_t size;
+ void __iomem *regs;
+ int irq;
+ int err;
+ int i;
+ int channel_no;
+ struct clk *clk;
+ struct resource *res;
+ struct fh_axi_dma_adapt *fh_axi_adapt_obj;
+ struct axi_dma_platform_data driver_plat_data;
+ struct axi_dma_ops * p_ops;
+ struct device_node *np = pdev->dev.of_node;
+
+ if (np && !IS_ERR(np)) {
+ regs = of_iomap(np, 0);
+ if (!regs) {
+ err = -ENOMEM;
+ goto err_release_r;
+ }
+ irq = irq_of_parse_and_map(np, 0);
+ clk = of_clk_get(np, 0);
+ } else {
+ adapt_plat_info_get(&p_axi_plat, pdev);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ goto err_release_r;
+ }
+ regs = ioremap(res->start, resource_size(res));
+ if (regs == NULL) {
+ dev_err(&pdev->dev, "ioremap resource error\n");
+ goto err_release_r;
+ }
+ irq = platform_get_irq(pdev, 0);
+ irq = irq_create_mapping(NULL, irq);
+ clk = clk_get(&pdev->dev, p_axi_plat.clk_name);
+ if (IS_ERR(clk)) {
+ err = -EINVAL;
+ goto err_release_r;
+ }
+ }
+ clk_prepare_enable(clk);
+ channel_no = cal_axi_dma_channel(regs);
+ size = sizeof(struct fh_axi_dma_adapt) + channel_no * sizeof(struct fh_axi_dma_channel_adapt);
+ fh_axi_adapt_obj = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+
+ if (!pdev->dev.dma_mask) {
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ }
+ fh_axi_adapt_obj->pdev = pdev;
+ fh_axi_adapt_obj->clk = clk;
+
+ INIT_LIST_HEAD(&fh_axi_adapt_obj->dma.channels);
+ for (i = 0; i < channel_no; i++) {
+ struct dma_chan *dma_channel;
+ spin_lock_init(&fh_axi_adapt_obj->chan[i].lock);
+ dma_channel = &fh_axi_adapt_obj->chan[i].core_chan;
+ dma_channel->device = &fh_axi_adapt_obj->dma;
+ dma_cookie_init(dma_channel);
+ list_add_tail(&dma_channel->device_node,
+ &fh_axi_adapt_obj->dma.channels);
+ }
+
+ driver_plat_data.id = pdev->id;
+ driver_plat_data.name = "axi_dma_driver";
+ driver_plat_data.base = (unsigned int)regs;
+ driver_plat_data.kernel_pri = (void *)fh_axi_adapt_obj->dma.dev;
+ driver_plat_data.adapt_pri = fh_axi_adapt_obj;
+
+
+ fh_axi_adapt_obj->driver_pri = fh_axi_dma_probe(&driver_plat_data);
+ if(!fh_axi_adapt_obj->driver_pri)
+ BUG_ON(1);
+
+ platform_set_drvdata(pdev, fh_axi_adapt_obj);
+ fh_axi_adapt_obj->dma.dev = &pdev->dev;
+ fh_axi_adapt_obj->dma.device_alloc_chan_resources = adapt_alloc_chan_resources;
+ fh_axi_adapt_obj->dma.device_free_chan_resources = adapt_free_chan_resources;
+ fh_axi_adapt_obj->dma.device_prep_dma_memcpy = adapt_prep_dma_memcpy;
+ fh_axi_adapt_obj->dma.device_prep_slave_sg = adapt_prep_slave_sg;
+ fh_axi_adapt_obj->dma.device_config = adapt_device_config;
+ fh_axi_adapt_obj->dma.device_pause = adapt_device_pause;
+ fh_axi_adapt_obj->dma.device_resume = adapt_device_resume;
+ fh_axi_adapt_obj->dma.device_terminate_all = adapt_device_terminate_all;
+ fh_axi_adapt_obj->dma.device_tx_status = adapt_tx_status;
+ fh_axi_adapt_obj->dma.device_issue_pending = adapt_device_issue_pending;
+
+ tasklet_init(&fh_axi_adapt_obj->tasklet, adapt_axi_dma_tasklet, (unsigned long)fh_axi_adapt_obj);
+ err = devm_request_irq(&pdev->dev, irq, adapt_dma_interrupt, 0,
+ "fh-axi-dmac", fh_axi_adapt_obj);
+ BUG_ON(err);
+
+ dma_cap_set(DMA_MEMCPY, fh_axi_adapt_obj->dma.cap_mask);
+ dma_cap_set(DMA_SLAVE, fh_axi_adapt_obj->dma.cap_mask);
+
+ trans.dma_number = pdev->id;
+ p_ops = get_fh_axi_dma_ops(fh_axi_adapt_obj->driver_pri);
+ p_ops->axi_dma_control(fh_axi_adapt_obj->driver_pri, AXI_DMA_CTRL_DMA_OPEN, &trans);
+ err = dma_async_device_register(&fh_axi_adapt_obj->dma);
+ if (err)
+ pr_err("dma register failed, ret %d\n", err);
+
+ dev_info(&pdev->dev, "FH DMA Controller, %d channels\n", channel_no);
+ return 0;
+
+err_release_r:
+ return err;
+}
+
+static int fh_axi_dma_adapt_remove(struct platform_device *pdev)
+{
+
+ struct fh_axi_dma_adapt *fh_axi_adapt_obj;
+ struct dma_transfer trans;
+ struct axi_dma_ops * p_ops;
+
+ //dma off
+ trans.dma_number = pdev->id;
+ fh_axi_adapt_obj = platform_get_drvdata(pdev);
+ p_ops = get_fh_axi_dma_ops(fh_axi_adapt_obj->driver_pri);
+ p_ops->axi_dma_control(fh_axi_adapt_obj->driver_pri, AXI_DMA_CTRL_DMA_CLOSE, &trans);
+ //kill tasklet
+ tasklet_kill(&fh_axi_adapt_obj->tasklet);
+ //unregister dma
+ dma_async_device_unregister(&fh_axi_adapt_obj->dma);
+ devm_kfree(&pdev->dev, fh_axi_adapt_obj);
+ return 0;
+}
+
+void fh_axi_dma_adapt_shutdown(struct platform_device *pdev){
+ pr_err("%s : %d.....\n",__func__,__LINE__);
+}
+
+
+
+
+static const struct of_device_id fh_axi_dma_adapt_of_id_table[] = {
+ { .compatible = "fh,fh-axi-dmac" },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, fh_axi_dma_adapt_of_id_table);
+
+static struct platform_driver fh_dma_axi_adapt_driver = {
+ .probe = fh_axi_dma_adapt_probe,
+ .remove = fh_axi_dma_adapt_remove,
+ .shutdown = fh_axi_dma_adapt_shutdown,
+ .driver = {
+ .name = "fh_axi_dmac",
+ .of_match_table = fh_axi_dma_adapt_of_id_table,
+ },
+};
+
+static int __init fh_axi_dma_adapt_init(void)
+{
+ return platform_driver_register(&fh_dma_axi_adapt_driver);
+}
+subsys_initcall(fh_axi_dma_adapt_init);
+
+static void __exit fh_axi_dma_adapt_exit(void)
+{
+ platform_driver_unregister(&fh_dma_axi_adapt_driver);
+}
+module_exit(fh_axi_dma_adapt_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("fullhan AXI-DMA devive driver");
+
+
diff --git a/drivers/dma/fh_axi_dma_adapt.h b/drivers/dma/fh_axi_dma_adapt.h
new file mode 100644
index 00000000..a1e57f67
--- /dev/null
+++ b/drivers/dma/fh_axi_dma_adapt.h
@@ -0,0 +1,213 @@
+#ifndef _FH_AXI_DMA_ADAPT_H
+#define _FH_AXI_DMA_ADAPT_H
+
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/io.h>
+#include <linux/irqreturn.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <asm/irq.h>
+#include <linux/dmaengine.h>
+#include "dmaengine.h"
+#include <linux/fh_dmac.h>
+#include <mach/fh_dma_plat.h>
+
+
+enum {
+ AXI_DMA_RET_OK = 0,
+ AXI_DMA_RET_NO_MEM = 1,
+};
+
+enum {
+ AXI_DMA_CTRL_DMA_OPEN = 0,
+ AXI_DMA_CTRL_DMA_CLOSE,
+ AXI_DMA_CTRL_DMA_REQUEST_CHANNEL,
+ AXI_DMA_CTRL_DMA_RELEASE_CHANNEL,
+ AXI_DMA_CTRL_DMA_SINGLE_TRANSFER,
+ AXI_DMA_CTRL_DMA_CYCLIC_PREPARE,
+ AXI_DMA_CTRL_DMA_CYCLIC_START,
+ AXI_DMA_CTRL_DMA_CYCLIC_STOP,
+ AXI_DMA_CTRL_DMA_CYCLIC_FREE,
+ AXI_DMA_CTRL_DMA_PAUSE,
+ AXI_DMA_CTRL_DMA_RESUME,
+ AXI_DMA_CTRL_DMA_GET_DAR,
+ AXI_DMA_CTRL_DMA_GET_SAR,
+};
+
+#define FH_CHANNEL_MAX_TRANSFER_SIZE (4096)
+#define MASTER_SEL_ENABLE 0x55
+#ifdef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+#define DESC_MAX_SIZE CONFIG_CHANNEL_ALLOC_DESC_NUM
+#else
+#define DESC_MAX_SIZE 128
+#endif
+#define DMA_CONTROLLER_NUMBER 1
+
+#define DMA_COMMON_ISR_OPEN 1
+#define DMA_COMMON_ISR_CLOSE 0
+#define DW_DMA_SLAVE_WIDTH_8BIT (0)
+#define DW_DMA_SLAVE_WIDTH_16BIT (1)
+#define DW_DMA_SLAVE_WIDTH_32BIT (2)
+
+
+/* the user should reference the hw handshaking watermark.. */
+#define DW_DMA_SLAVE_MSIZE_1 (0)
+#define DW_DMA_SLAVE_MSIZE_4 (1)
+#define DW_DMA_SLAVE_MSIZE_8 (2)
+#define DW_DMA_SLAVE_MSIZE_16 (3)
+#define DW_DMA_SLAVE_MSIZE_32 (4)
+#define DW_DMA_SLAVE_MSIZE_64 (5)
+#define DW_DMA_SLAVE_MSIZE_128 (6)
+#define DW_DMA_SLAVE_MSIZE_256 (7)
+
+
+#define DW_DMA_SLAVE_INC (0)
+#define DW_DMA_SLAVE_DEC (1)
+#define DW_DMA_SLAVE_FIX (2)
+#define DMA_M2M (0) /* MEM <=> MEM */
+#define DMA_M2P (1) /* MEM => peripheral A */
+#define DMA_P2M (2) /* MEM <= peripheral A */
+#define DMA_P2P (3) /* peripheral A <=> peripheral B */
+#define AUTO_FIND_CHANNEL (0xff)
+#define DMA_HW_HANDSHAKING (0)
+#define DMA_SW_HANDSHAKING (1)
+#define ADDR_RELOAD (0x55)
+
+/* Platform-configurable bits in CFG_HI */
+#define FHC_CFGH_FCMODE (1 << 0)
+#define FHC_CFGH_FIFO_MODE (1 << 1)
+#define FHC_CFGH_PROTCTL(x) ((x) << 2)
+#define FHC_CFGH_SRC_PER(x) ((x) << 7)
+#define FHC_CFGH_DST_PER(x) ((x) << 11)
+
+/* Platform-configurable bits in CFG_LO */
+#define FHC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */
+#define FHC_CFGL_LOCK_CH_BLOCK (1 << 12)
+#define FHC_CFGL_LOCK_CH_XACT (2 << 12)
+#define FHC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */
+#define FHC_CFGL_LOCK_BUS_BLOCK (1 << 14)
+#define FHC_CFGL_LOCK_BUS_XACT (2 << 14)
+#define FHC_CFGL_LOCK_CH (1 << 15) /* channel lockout */
+#define FHC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */
+#define FHC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */
+#define FHC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */
+
+
+typedef void (*dma_complete_callback)(void *complete_para);
+
+
+/* controller private para... */
+struct fh_axi_dma;
+struct dma_transfer;
+
+struct axi_dma_ops {
+ void (*axi_dma_isr_process)(struct fh_axi_dma *param);
+ void (*axi_dma_isr_enable_set)(struct fh_axi_dma *param,
+ FH_UINT32 enable);
+ FH_SINT32(*axi_dma_control)(struct fh_axi_dma *dma,
+ FH_UINT32 cmd, struct dma_transfer *arg);
+ void (*axi_dma_get_desc_para)(struct fh_axi_dma *dma,
+ struct dma_transfer *p_transfer,
+ FH_UINT32 *desc_size, FH_UINT32 *base_phy_add,
+ FH_UINT32 *each_desc_size, FH_UINT32 *each_desc_cap);
+};
+
+struct axi_dma_platform_data {
+ FH_UINT32 id;
+ FH_UINT8 *name;
+ //FH_UINT32 irq;
+ FH_UINT32 base;
+ FH_UINT32 channel_max_number;
+ //bind to kernel pri
+ void *kernel_pri;
+ void *adapt_pri;
+};
+
+struct dma_transfer_desc {
+ FH_UINT32 src_width;
+ FH_UINT32 src_msize;
+ FH_UINT32 src_add;
+ FH_UINT32 src_inc_mode;
+
+ FH_UINT32 dst_width;
+ FH_UINT32 dst_msize;
+ FH_UINT32 dst_add;
+ FH_UINT32 dst_inc_mode;
+
+ FH_UINT32 size;
+};
+/* transfer use below */
+struct dma_transfer {
+ axi_dma_list transfer_list;
+ struct fh_axi_dma *dma_controller;
+ void *first_lli;
+ FH_UINT32 lli_size;
+ /* new add for allign get desc... */
+ FH_UINT32 actual_lli_size;
+ FH_UINT32 channel_number;
+ /* which dma you want to use...for fh81....only 0!!! */
+ FH_UINT32 dma_number;
+ FH_UINT32 fc_mode; /* ip->mem. mem->mem. mem->ip */
+ FH_UINT32 src_hs; /* src */
+ FH_UINT32 src_per; /* src hw handshake number */
+ FH_UINT32 dst_hs; /* src */
+ FH_UINT32 dst_per;
+ FH_UINT32 trans_len;
+ /* this is used when dma finish transfer job */
+ dma_complete_callback complete_callback;
+ void *complete_para; /* for the driver data use the dma driver. */
+ /* private para.. */
+ void (*prepare_callback)(void *p);
+ void *prepare_para;
+
+ void (*isr_prepare_callback)(void *p);
+ void *isr_prepare_para;
+
+ FH_UINT32 period_len;
+ FH_UINT32 master_flag;
+ FH_UINT32 src_master;
+ FH_UINT32 dst_master;
+ FH_UINT32 cyclic_periods;
+
+ struct dma_transfer_desc *p_desc;
+ FH_UINT32 desc_size;
+
+};
+
+
+struct fh_axi_dma_channel_adapt {
+ struct dma_chan core_chan;
+ struct dma_transfer trans;
+ struct fh_dma_extra ext_para;
+ struct dma_async_tx_descriptor *ch_adapt_desc_base;
+ struct dma_transfer_desc *desc_head;
+ u32 desc_size;
+ struct dma_slave_config sconfig;
+ struct fh_cyclic_desc cyclic;
+ spinlock_t lock;
+};
+
+struct fh_axi_dma_adapt {
+ struct dma_device dma;
+ struct tasklet_struct tasklet;
+ struct clk *clk;
+ //bind to driver data. help to find the driver handle
+ struct fh_axi_dma *driver_pri;
+ struct platform_device *pdev;
+ struct fh_axi_dma_channel_adapt chan[0];
+
+};
+
+FH_UINT32 cal_axi_dma_channel(void *regs);
+struct axi_dma_ops *get_fh_axi_dma_ops(struct fh_axi_dma *p_axi_dma);
+struct fh_axi_dma *fh_axi_dma_probe(struct axi_dma_platform_data *priv_data);
+
+#endif
diff --git a/drivers/dma/fh_axi_dma_driver.c b/drivers/dma/fh_axi_dma_driver.c
new file mode 100644
index 00000000..b806bd69
--- /dev/null
+++ b/drivers/dma/fh_axi_dma_driver.c
@@ -0,0 +1,1400 @@
+#include "fh_axi_dma_adapt.h"
+
+
+#ifndef BIT
+#define BIT(x) (1 << (x))
+#endif
+
+//#define AXI_DMA_DEBUG
+#define AXI_DESC_ALLIGN 64 /*DO NOT TOUCH!!!*/
+#define AXI_DESC_ALLIGN_BIT_MASK 0x7f /*DO NOT TOUCH!!!*/
+#define lift_shift_bit_num(bit_num) (1 << bit_num)
+#define AXI_DMA_MAX_NR_CHANNELS 8
+#ifndef GENMASK
+#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h))))
+#endif
+#ifndef GENMASK_ULL
+#define GENMASK_ULL(h, l) \
+ (((~0ULL) << (l)) & (~0ULL >> (sizeof(long long) * 8 - 1 - (h))))
+#endif
+
+/* DMAC_CFG */
+#define DMAC_EN_POS 0
+#define DMAC_EN_MASK BIT(DMAC_EN_POS)
+#define INT_EN_POS 1
+#define INT_EN_MASK BIT(INT_EN_POS)
+/* CH_CTL_H */
+#define CH_CTL_H_ARLEN_EN(n) ((n) << 6) /* 32+6 = 38 */
+#define CH_CTL_H_ARLEN(n) ((n) << 7) /* 32+7 = 39 */
+#define CH_CTL_H_AWLEN_EN(n) ((n) << 15) /* 32+15 = 47 */
+#define CH_CTL_H_AWLEN(n) ((n) << 16) /* 32+16 = 48 */
+#define CH_CTL_H_IOC_BLKTFR BIT(26)
+#define CH_CTL_H_LLI_LAST BIT(30)
+#define CH_CTL_H_LLI_VALID BIT(31)
+
+/* CH_CTL_L */
+#define CH_CTL_L_LAST_WRITE_EN BIT(30)
+#define CH_CTL_L_AR_CACHE(n) ((n) << 22)
+#define CH_CTL_L_AW_CACHE(n) ((n) << 26)
+#define CH_CTL_L_DST_WIDTH_POS 11
+#define CH_CTL_L_SRC_WIDTH_POS 8
+#define CH_CTL_L_DST_INC_POS 6
+#define CH_CTL_L_SRC_INC_POS 4
+#define CH_CTL_L_DST_MAST BIT(2)
+#define CH_CTL_L_SRC_MAST BIT(0)
+
+/* CH_CFG_H */
+#define CH_CFG_H_PRIORITY_POS 17
+#define CH_CFG_H_HS_SEL_DST_POS 4
+#define CH_CFG_H_HS_SEL_SRC_POS 3
+#define CH_CFG_H_TT_FC_POS 0
+
+#define CH_CFG_H_DST_OSR_LMT(n) ((n) << 27)
+#define CH_CFG_H_SRC_OSR_LMT(n) ((n) << 23)
+/* CH_CFG_L */
+#define CH_CFG_L_DST_MULTBLK_TYPE_POS 2
+#define CH_CFG_L_SRC_MULTBLK_TYPE_POS 0
+
+#define AXI_DMA_CTLL_DST_WIDTH(n) ((n) << 11) /* bytes per element */
+#define AXI_DMA_CTLL_SRC_WIDTH(n) ((n) << 8)
+#define AXI_DMA_CTLL_DST_INC_MODE(n) ((n) << 6)
+#define AXI_DMA_CTLL_SRC_INC_MODE(n) ((n) << 4)
+
+#define AXI_DMA_CTLL_DST_MSIZE(n) ((n) << 18)
+#define AXI_DMA_CTLL_SRC_MSIZE(n) ((n) << 14)
+
+
+#define AXI_DMA_CTLL_DMS(n) ((n) << 2)
+#define AXI_DMA_CTLL_SMS(n) ((n) << 0)
+/* caution ,diff with ahb dma */
+#define AXI_DMA_CFGH_FC(n) ((n) << 0)
+#define AXI_DMA_CFGH_DST_PER(n) ((n) << 3)
+
+#define DW_REG(name) \
+ FH_UINT32 name; \
+ FH_UINT32 __pad_##name
+
+
+#define __dma_raw_writeb(v, a) (*(volatile FH_UINT8 *)(a) = (v))
+#define __dma_raw_writew(v, a) (*(volatile FH_UINT16 *)(a) = (v))
+#define __dma_raw_writel(v, a) (*(volatile FH_UINT32 *)(a) = (v))
+
+#define __dma_raw_readb(a) (*(volatile FH_UINT8 *)(a))
+#define __dma_raw_readw(a) (*(volatile FH_UINT16 *)(a))
+#define __dma_raw_readl(a) (*(volatile FH_UINT32 *)(a))
+
+#define dw_readl(dw, name) \
+ __dma_raw_readl(&(((struct dw_axi_dma_regs *)dw->regs)->name))
+#define dw_writel(dw, name, val) \
+ __dma_raw_writel((val), &(((struct dw_axi_dma_regs *)dw->regs)->name))
+#define dw_readw(dw, name) \
+ __dma_raw_readw(&(((struct dw_axi_dma_regs *)dw->regs)->name))
+#define dw_writew(dw, name, val) \
+ __dma_raw_writew((val), &(((struct dw_axi_dma_regs *)dw->regs)->name))
+
+#define CONTROLLER_STATUS_CLOSED (0)
+#define CONTROLLER_STATUS_OPEN (1)
+
+#define CHANNEL_STATUS_CLOSED (0)
+#define CHANNEL_STATUS_OPEN (1)
+#define CHANNEL_STATUS_IDLE (2)
+#define CHANNEL_STATUS_BUSY (3)
+#define SINGLE_TRANSFER (0)
+#define CYCLIC_TRANSFER (1)
+#define DEFAULT_TRANSFER SINGLE_TRANSFER
+#define CHANNEL_REAL_FREE (0)
+#define CHANNEL_NOT_FREE (1)
+
+#define axi_dma_list_entry(node, type, member) \
+ ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
+
+#define axi_dma_list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = axi_dma_list_entry((head)->next, typeof(*pos), member), \
+ n = axi_dma_list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = axi_dma_list_entry(n->member.next, typeof(*n), member))
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type that only be used in this file here
+ ***************************************************************************/
+enum {
+ DWAXIDMAC_ARWLEN_1 = 0,
+ DWAXIDMAC_ARWLEN_2 = 1,
+ DWAXIDMAC_ARWLEN_4 = 3,
+ DWAXIDMAC_ARWLEN_8 = 7,
+ DWAXIDMAC_ARWLEN_16 = 15,
+ DWAXIDMAC_ARWLEN_32 = 31,
+ DWAXIDMAC_ARWLEN_64 = 63,
+ DWAXIDMAC_ARWLEN_128 = 127,
+ DWAXIDMAC_ARWLEN_256 = 255,
+ DWAXIDMAC_ARWLEN_MIN = DWAXIDMAC_ARWLEN_1,
+ DWAXIDMAC_ARWLEN_MAX = DWAXIDMAC_ARWLEN_256
+};
+
+enum {
+ DWAXIDMAC_BURST_TRANS_LEN_1 = 0,
+ DWAXIDMAC_BURST_TRANS_LEN_4,
+ DWAXIDMAC_BURST_TRANS_LEN_8,
+ DWAXIDMAC_BURST_TRANS_LEN_16,
+ DWAXIDMAC_BURST_TRANS_LEN_32,
+ DWAXIDMAC_BURST_TRANS_LEN_64,
+ DWAXIDMAC_BURST_TRANS_LEN_128,
+ DWAXIDMAC_BURST_TRANS_LEN_256,
+ DWAXIDMAC_BURST_TRANS_LEN_512,
+ DWAXIDMAC_BURST_TRANS_LEN_1024
+};
+
+enum {
+ DWAXIDMAC_CH_CTL_L_INC = 0,
+ DWAXIDMAC_CH_CTL_L_NOINC
+};
+
+enum {
+ DWAXIDMAC_HS_SEL_HW = 0,
+ DWAXIDMAC_HS_SEL_SW
+};
+
+enum {
+ DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC = 0,
+ DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC,
+ DWAXIDMAC_TT_FC_PER_TO_MEM_DMAC,
+ DWAXIDMAC_TT_FC_PER_TO_PER_DMAC,
+ DWAXIDMAC_TT_FC_PER_TO_MEM_SRC,
+ DWAXIDMAC_TT_FC_PER_TO_PER_SRC,
+ DWAXIDMAC_TT_FC_MEM_TO_PER_DST,
+ DWAXIDMAC_TT_FC_PER_TO_PER_DST
+};
+
+enum {
+ DWAXIDMAC_MBLK_TYPE_CONTIGUOUS = 0,
+ DWAXIDMAC_MBLK_TYPE_RELOAD,
+ DWAXIDMAC_MBLK_TYPE_SHADOW_REG,
+ DWAXIDMAC_MBLK_TYPE_LL
+};
+
+
+/**
+ * DW AXI DMA channel interrupts
+ *
+ * @DWAXIDMAC_IRQ_NONE: Bitmask of no one interrupt
+ * @DWAXIDMAC_IRQ_BLOCK_TRF: Block transfer complete
+ * @DWAXIDMAC_IRQ_DMA_TRF: Dma transfer complete
+ * @DWAXIDMAC_IRQ_SRC_TRAN: Source transaction complete
+ * @DWAXIDMAC_IRQ_DST_TRAN: Destination transaction complete
+ * @DWAXIDMAC_IRQ_SRC_DEC_ERR: Source decode error
+ * @DWAXIDMAC_IRQ_DST_DEC_ERR: Destination decode error
+ * @DWAXIDMAC_IRQ_SRC_SLV_ERR: Source slave error
+ * @DWAXIDMAC_IRQ_DST_SLV_ERR: Destination slave error
+ * @DWAXIDMAC_IRQ_LLI_RD_DEC_ERR: LLI read decode error
+ * @DWAXIDMAC_IRQ_LLI_WR_DEC_ERR: LLI write decode error
+ * @DWAXIDMAC_IRQ_LLI_RD_SLV_ERR: LLI read slave error
+ * @DWAXIDMAC_IRQ_LLI_WR_SLV_ERR: LLI write slave error
+ * @DWAXIDMAC_IRQ_INVALID_ERR: LLI invalid error or Shadow register error
+ * @DWAXIDMAC_IRQ_MULTIBLKTYPE_ERR: Slave Interface Multiblock type error
+ * @DWAXIDMAC_IRQ_DEC_ERR: Slave Interface decode error
+ * @DWAXIDMAC_IRQ_WR2RO_ERR: Slave Interface write to read only error
+ * @DWAXIDMAC_IRQ_RD2RWO_ERR: Slave Interface read to write only error
+ * @DWAXIDMAC_IRQ_WRONCHEN_ERR: Slave Interface write to channel error
+ * @DWAXIDMAC_IRQ_SHADOWREG_ERR: Slave Interface shadow reg error
+ * @DWAXIDMAC_IRQ_WRONHOLD_ERR: Slave Interface hold error
+ * @DWAXIDMAC_IRQ_LOCK_CLEARED: Lock Cleared Status
+ * @DWAXIDMAC_IRQ_SRC_SUSPENDED: Source Suspended Status
+ * @DWAXIDMAC_IRQ_SUSPENDED: Channel Suspended Status
+ * @DWAXIDMAC_IRQ_DISABLED: Channel Disabled Status
+ * @DWAXIDMAC_IRQ_ABORTED: Channel Aborted Status
+ * @DWAXIDMAC_IRQ_ALL_ERR: Bitmask of all error interrupts
+ * @DWAXIDMAC_IRQ_ALL: Bitmask of all interrupts
+ */
+enum {
+ DWAXIDMAC_IRQ_NONE = 0,
+ DWAXIDMAC_IRQ_BLOCK_TRF = BIT(0),
+ DWAXIDMAC_IRQ_DMA_TRF = BIT(1),
+ DWAXIDMAC_IRQ_SRC_TRAN = BIT(3),
+ DWAXIDMAC_IRQ_DST_TRAN = BIT(4),
+ DWAXIDMAC_IRQ_SRC_DEC_ERR = BIT(5),
+ DWAXIDMAC_IRQ_DST_DEC_ERR = BIT(6),
+ DWAXIDMAC_IRQ_SRC_SLV_ERR = BIT(7),
+ DWAXIDMAC_IRQ_DST_SLV_ERR = BIT(8),
+ DWAXIDMAC_IRQ_LLI_RD_DEC_ERR = BIT(9),
+ DWAXIDMAC_IRQ_LLI_WR_DEC_ERR = BIT(10),
+ DWAXIDMAC_IRQ_LLI_RD_SLV_ERR = BIT(11),
+ DWAXIDMAC_IRQ_LLI_WR_SLV_ERR = BIT(12),
+ DWAXIDMAC_IRQ_INVALID_ERR = BIT(13),
+ DWAXIDMAC_IRQ_MULTIBLKTYPE_ERR = BIT(14),
+ DWAXIDMAC_IRQ_DEC_ERR = BIT(16),
+ DWAXIDMAC_IRQ_WR2RO_ERR = BIT(17),
+ DWAXIDMAC_IRQ_RD2RWO_ERR = BIT(18),
+ DWAXIDMAC_IRQ_WRONCHEN_ERR = BIT(19),
+ DWAXIDMAC_IRQ_SHADOWREG_ERR = BIT(20),
+ DWAXIDMAC_IRQ_WRONHOLD_ERR = BIT(21),
+ DWAXIDMAC_IRQ_LOCK_CLEARED = BIT(27),
+ DWAXIDMAC_IRQ_SRC_SUSPENDED = BIT(28),
+ DWAXIDMAC_IRQ_SUSPENDED = BIT(29),
+ DWAXIDMAC_IRQ_DISABLED = BIT(30),
+ DWAXIDMAC_IRQ_ABORTED = BIT(31),
+ DWAXIDMAC_IRQ_ALL_ERR = (GENMASK(21, 16) | GENMASK(14, 5)),
+ DWAXIDMAC_IRQ_ALL = GENMASK(31, 0)
+};
+
+struct axi_dma_lli {
+ FH_UINT32 sar_lo;
+ FH_UINT32 sar_hi;
+ FH_UINT32 dar_lo;
+ FH_UINT32 dar_hi;
+ FH_UINT32 block_ts_lo;
+ FH_UINT32 block_ts_hi;
+ FH_UINT32 llp_lo;
+ FH_UINT32 llp_hi;
+ FH_UINT32 ctl_lo;
+ FH_UINT32 ctl_hi;
+ FH_UINT32 sstat;
+ FH_UINT32 dstat;
+ FH_UINT32 status_lo;
+ FH_UINT32 status_hi;
+ FH_UINT32 reserved_lo;
+ FH_UINT32 reserved_hi;
+};
+
+/* Hardware register definitions. */
+struct dw_axi_dma_chan_regs {
+ DW_REG(SAR); /* 0x0 ~ 0x7*/
+ DW_REG(DAR); /* 0x8 ~ 0xf*/
+ DW_REG(BLOCK_TS); /* 0x10 ~ 0x17*/
+ FH_UINT32 CTL_LO;
+ FH_UINT32 CTL_HI; /* 0x18 ~ 0x1f*/
+ FH_UINT32 CFG_LO;
+ FH_UINT32 CFG_HI; /* 0x20 ~ 0x27*/
+ DW_REG(LLP); /* 0x28 ~ 0x2f*/
+ FH_UINT32 STATUS_LO;
+ FH_UINT32 STATUS_HI; /* 0x30 ~ 0x37*/
+ DW_REG(SWHS_SRC); /* 0x38 ~ 0x3f*/
+ DW_REG(SWHS_DST); /* 0x40 ~ 0x47*/
+ DW_REG(BLK_TFR_RESU);
+ DW_REG(ID);
+ DW_REG(QOS);
+ DW_REG(SSTAT);
+ DW_REG(DSTAT);
+ DW_REG(SSTATAR);
+ DW_REG(DSTATAR);
+ FH_UINT32 INTSTATUS_EN_LO;
+ FH_UINT32 INTSTATUS_EN_HI;
+ FH_UINT32 INTSTATUS_LO;
+ FH_UINT32 INTSTATUS_HI;
+ FH_UINT32 INTSIGNAL_LO;
+ FH_UINT32 INTSIGNAL_HI;
+ FH_UINT32 INTCLEAR_LO;
+ FH_UINT32 INTCLEAR_HI;
+ FH_UINT32 rev[24];
+};
+
+struct dw_axi_dma_regs {
+ DW_REG(ID); /* 0x0 */
+ DW_REG(COMPVER); /* 0x8 */
+ DW_REG(CFG); /* 0x10 */
+ FH_UINT32 CHEN_LO; /* 0x18 */
+ FH_UINT32 CHEN_HI; /* 0x1c */
+ DW_REG(reserved_20_27); /* 0x20 */
+ DW_REG(reserved_28_2f); /* 0x28 */
+ DW_REG(INTSTATUS); /* 0x30 */
+ DW_REG(COM_INTCLEAR); /* 0x38 */
+ DW_REG(COM_INTSTATUS_EN); /* 0x40 */
+ DW_REG(COM_INTSIGNAL_EN); /* 0x48 */
+ DW_REG(COM_INTSTATUS); /* 0x50 */
+ DW_REG(RESET); /* 0x58 */
+ FH_UINT32 reserved[40]; /* 0x60 */
+ struct dw_axi_dma_chan_regs CHAN[AXI_DMA_MAX_NR_CHANNELS];/* 0x100 */
+};
+
+struct dw_axi_dma {
+ /* vadd */
+ void *regs;
+ FH_UINT32 channel_max_number;
+ FH_UINT32 controller_status;
+ FH_UINT32 id;
+ char name[20];
+};
+
+struct dma_channel {
+ FH_UINT32 channel_status; /* open, busy ,closed */
+ FH_UINT32 desc_trans_size;
+ axi_dma_lock_t channel_lock;
+ axi_dma_list queue;
+ struct dma_transfer *active_trans;
+ FH_UINT32 open_flag;
+ FH_UINT32 desc_total_no;
+ FH_UINT32 free_index;
+ FH_UINT32 used_index;
+ FH_UINT32 desc_left_cnt;
+ /*malloc maybe not allign; driver will malloc (size + cache line) incase*/
+ FH_UINT32 allign_malloc;
+ FH_UINT32 allign_phy;
+ struct axi_dma_lli *base_lli;
+ FH_UINT32 base_lli_phy;
+ FH_UINT32 int_sig;
+ FH_UINT32 status;
+};
+
+struct fh_axi_dma {
+ /* myown */
+ void *kernel_pri;// used for malloc........
+ void *adapt_pri;// use for call adapt driver
+ struct axi_dma_ops ops;
+ struct dw_axi_dma dwc;
+ /* channel obj */
+ struct dma_channel dma_channel[AXI_DMA_MAX_NR_CHANNELS];
+};
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+
+/*****************************************************************************
+ * static fun;
+ *****************************************************************************/
+static void fh_axi_dma_cyclic_stop(struct dma_transfer *p);
+static void fh_axi_dma_cyclic_start(struct dma_transfer *p);
+static void fh_axi_dma_cyclic_prep(struct fh_axi_dma *fh_dma_p,
+struct dma_transfer *p);
+static void fh_axi_dma_cyclic_free(struct dma_transfer *p);
+static void fh_axi_dma_cyclic_pause(struct dma_transfer *p);
+static void fh_axi_dma_cyclic_resume(struct dma_transfer *p);
+static FH_UINT32 vir_lli_to_phy_lli(struct axi_dma_lli *base_lli,
+FH_UINT32 base_lli_phy, struct axi_dma_lli *cal_lli);
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+
+/* function body */
+/*****************************************************************************
+ * Description:
+ * add funtion description here
+ * Parameters:
+ * description for each argument, new argument starts at new line
+ * Return:
+ * what does this function returned?
+ *****************************************************************************/
+
+static void dump_lli(struct axi_dma_lli *p_lli, struct axi_dma_lli *base_lli, FH_UINT32 base_lli_phy)
+{
+ FH_UINT32 phy_add;
+
+ phy_add = vir_lli_to_phy_lli(base_lli, base_lli_phy, p_lli);
+
+ FH_AXI_DMA_PRINT("SAR: 0x%08x DAR: 0x%08x LLP: 0x%08x BTS 0x%08x CTL: 0x%08x:%08x LLI_PHY_ADD: 0x%x\n",
+ (p_lli->sar_lo),
+ (p_lli->dar_lo),
+ (p_lli->llp_lo),
+ (p_lli->block_ts_lo),
+ (p_lli->ctl_hi),
+ (p_lli->ctl_lo),
+ (FH_UINT32)phy_add);
+
+}
+
+static void dump_channel_reg(struct fh_axi_dma *p_dma, struct dma_transfer *p_transfer)
+{
+ struct dw_axi_dma *temp_dwc;
+
+ FH_UINT32 chan_no = p_transfer->channel_number;
+
+ temp_dwc = &p_dma->dwc;
+
+ FH_AXI_DMA_PRINT("[CHAN : %d]SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x CFG: 0x%x:%08x INTEN :0x%x INTSTATUS: 0x%x\n",
+ chan_no,
+ dw_readl(temp_dwc, CHAN[chan_no].SAR),
+ dw_readl(temp_dwc, CHAN[chan_no].DAR),
+ dw_readl(temp_dwc, CHAN[chan_no].LLP),
+ dw_readl(temp_dwc, CHAN[chan_no].CTL_HI),
+ dw_readl(temp_dwc, CHAN[chan_no].CTL_LO),
+ dw_readl(temp_dwc, CHAN[chan_no].CFG_HI),
+ dw_readl(temp_dwc, CHAN[chan_no].CFG_LO),
+ dw_readl(temp_dwc, CHAN[chan_no].INTSTATUS_EN_LO),
+ dw_readl(temp_dwc, CHAN[chan_no].INTSTATUS_LO)
+ );
+
+}
+
+static void dump_dma_common_reg(struct fh_axi_dma *p_dma)
+{
+ struct dw_axi_dma *temp_dwc;
+
+ temp_dwc = &p_dma->dwc;
+ if (!temp_dwc->regs)
+ return;
+ FH_AXI_DMA_PRINT("ID: 0x%x COMPVER: 0x%x CFG: 0x%x CHEN: 0x%x:%08x INTSTATUS: 0x%x\
+ COM_INTSTATUS_EN: 0x%x COM_INTSIGNAL_EN: %x COM_INTSTATUS: %x\n",
+ dw_readl(temp_dwc, ID),
+ dw_readl(temp_dwc, COMPVER),
+ dw_readl(temp_dwc, CFG),
+ dw_readl(temp_dwc, CHEN_HI),
+ dw_readl(temp_dwc, CHEN_LO),
+ dw_readl(temp_dwc, INTSTATUS),
+ dw_readl(temp_dwc, COM_INTSTATUS_EN),
+ dw_readl(temp_dwc, COM_INTSIGNAL_EN),
+ dw_readl(temp_dwc, COM_INTSTATUS)
+ );
+
+}
+
+
+static void dump_chan_xfer_info(struct fh_axi_dma *p_dma, struct dma_transfer *p_transfer)
+{
+ FH_UINT32 i;
+ struct axi_dma_lli *p_lli;
+
+ p_lli = (struct axi_dma_lli *)p_transfer->first_lli;
+ dump_dma_common_reg(p_dma);
+ dump_channel_reg(p_dma, p_transfer);
+ for (i = 0; i < p_transfer->desc_size; i++) {
+ dump_lli(&p_lli[i], p_dma->dma_channel[p_transfer->channel_number].base_lli,
+ p_dma->dma_channel[p_transfer->channel_number].base_lli_phy);
+ }
+}
+
+static FH_UINT32 allign_func(FH_UINT32 in_addr, FH_UINT32 allign_size, FH_UINT32 *phy_back_allign)
+{
+ *phy_back_allign = (*phy_back_allign + allign_size - 1) & (~(allign_size - 1));
+ return (in_addr + allign_size - 1) & (~(allign_size - 1));
+}
+
+static FH_UINT32 vir_lli_to_phy_lli(struct axi_dma_lli *base_lli,
+FH_UINT32 base_lli_phy, struct axi_dma_lli *cal_lli)
+{
+ FH_UINT32 ret;
+
+ ret = base_lli_phy + ((FH_UINT32)cal_lli - (FH_UINT32)base_lli);
+ return ret;
+}
+
+struct axi_dma_lli *get_desc(struct fh_axi_dma *p_dma,
+struct dma_transfer *p_transfer, FH_UINT32 lli_size)
+{
+ struct axi_dma_lli *ret_lli;
+ FH_UINT32 free_index;
+ FH_UINT32 allign_left;
+ FH_UINT32 totoal_desc;
+ FH_UINT32 actual_get_desc = 0;
+ FH_UINT32 totoal_free_desc;
+
+ totoal_free_desc =
+ p_dma->dma_channel[p_transfer->channel_number].desc_left_cnt;
+ free_index = p_dma->dma_channel[p_transfer->channel_number].free_index;
+ totoal_desc = p_dma->dma_channel[p_transfer->channel_number].desc_total_no;
+ allign_left = totoal_desc - free_index;
+
+ /* check first.. */
+ if (totoal_free_desc < lli_size) {
+ FH_AXI_DMA_PRINT("not enough desc to get...\n");
+ FH_AXI_DMA_PRINT("get size is %d,left is %d\n", lli_size, totoal_free_desc);
+ return AXI_DMA_NULL;
+ }
+
+ if (lli_size > allign_left) {
+ /* if allign desc not enough...just reset null.... */
+ if ((totoal_free_desc - allign_left) < lli_size) {
+ FH_AXI_DMA_PRINT("not enough desc to get...\n");
+ FH_AXI_DMA_PRINT(
+ "app need size is %d, totoal left is %d, allign left is %d\n",
+ lli_size, totoal_free_desc, allign_left);
+ FH_AXI_DMA_PRINT("from head to get desc size is %d, actual get is %d\n",
+ (totoal_free_desc - allign_left),
+ (allign_left + lli_size));
+ return AXI_DMA_NULL;
+ } else {
+ actual_get_desc = allign_left + lli_size;
+ free_index = 0;
+ }
+ }
+
+ ret_lli = &p_dma->dma_channel[p_transfer->channel_number].base_lli[free_index];
+ p_dma->dma_channel[p_transfer->channel_number].free_index +=
+ actual_get_desc;
+ p_dma->dma_channel[p_transfer->channel_number].free_index %=
+ p_dma->dma_channel[p_transfer->channel_number].desc_total_no;
+ p_dma->dma_channel[p_transfer->channel_number].desc_left_cnt -=
+ actual_get_desc;
+ p_transfer->lli_size = lli_size;
+ p_transfer->actual_lli_size = actual_get_desc;
+ return ret_lli;
+}
+
+FH_UINT32 put_desc(struct fh_axi_dma *p_dma, struct dma_transfer *p_transfer)
+{
+ FH_UINT32 lli_size;
+
+ lli_size = p_transfer->actual_lli_size;
+ p_dma->dma_channel[p_transfer->channel_number].used_index += lli_size;
+ p_dma->dma_channel[p_transfer->channel_number].used_index %=
+ p_dma->dma_channel[p_transfer->channel_number].desc_total_no;
+ p_dma->dma_channel[p_transfer->channel_number].desc_left_cnt += lli_size;
+ p_transfer->lli_size = 0;
+ p_transfer->actual_lli_size = 0;
+ return AXI_DMA_RET_OK;
+}
+
+#if defined CONFIG_ARCH_FH8636 || defined CONFIG_ARCH_FH8852V101
+#define axi_dma_reset(...)
+#else
+static void axi_dma_reset(struct dw_axi_dma *axi_dma_obj)
+{
+ FH_UINT32 ret;
+ FH_UINT32 time_out = 0xffffff;
+
+ dw_writel(axi_dma_obj, RESET, 1);
+ do {
+ ret = dw_readl(axi_dma_obj, RESET);
+ time_out--;
+ } while (ret && time_out);
+
+ if (!time_out)
+ FH_AXI_DMA_PRINT("%s : time out..\n", __func__);
+}
+#endif
+
+static void axi_dma_enable(struct dw_axi_dma *axi_dma_obj)
+{
+ FH_UINT32 ret;
+
+ ret = dw_readl(axi_dma_obj, CFG);
+ ret |= BIT(DMAC_EN_POS);
+ dw_writel(axi_dma_obj, CFG, ret);
+}
+
+static void axi_dma_isr_common_enable(struct dw_axi_dma *axi_dma_obj)
+{
+ FH_UINT32 ret;
+
+ ret = dw_readl(axi_dma_obj, CFG);
+ ret |= BIT(INT_EN_POS);
+ dw_writel(axi_dma_obj, CFG, ret);
+}
+
+static void axi_dma_isr_common_disable(struct dw_axi_dma *axi_dma_obj)
+{
+ FH_UINT32 ret;
+
+ ret = dw_readl(axi_dma_obj, CFG);
+ ret &= ~(BIT(INT_EN_POS));
+ dw_writel(axi_dma_obj, CFG, ret);
+}
+
+static void handle_dma_open(struct fh_axi_dma *p_dma)
+{
+ struct dw_axi_dma *temp_dwc;
+
+ temp_dwc = &p_dma->dwc;
+ axi_dma_enable(temp_dwc);
+ axi_dma_isr_common_enable(temp_dwc);
+ p_dma->dwc.controller_status = CONTROLLER_STATUS_OPEN;
+}
+
+static void handle_dma_close(struct fh_axi_dma *p_dma)
+{
+ FH_UINT32 i;
+ struct dw_axi_dma *temp_dwc;
+
+ temp_dwc = &p_dma->dwc;
+ /* take lock */
+ for (i = 0; i < p_dma->dwc.channel_max_number; i++)
+ p_dma->dma_channel[i].channel_status = CHANNEL_STATUS_CLOSED;
+
+ axi_dma_reset(temp_dwc);
+ p_dma->dwc.controller_status = CONTROLLER_STATUS_CLOSED;
+
+}
+
+
+static FH_UINT32 check_channel_real_free(struct fh_axi_dma *p_dma,
+FH_UINT32 channel_number)
+{
+ struct dw_axi_dma *temp_dwc;
+ FH_UINT32 ret_status;
+
+ temp_dwc = &p_dma->dwc;
+ AXI_DMA_ASSERT(channel_number < p_dma->dwc.channel_max_number);
+
+ ret_status = dw_readl(temp_dwc, CHEN_LO);
+ if (ret_status & lift_shift_bit_num(channel_number)) {
+ FH_AXI_DMA_PRINT("channel_number : %d is busy....\n", channel_number);
+ return CHANNEL_NOT_FREE;
+ }
+ return CHANNEL_REAL_FREE;
+}
+
+static FH_ERR handle_request_channel(struct fh_axi_dma *p_dma,
+struct dma_transfer *p_transfer)
+{
+ FH_UINT32 i;
+ FH_ERR ret_status = AXI_DMA_RET_OK;
+
+ if (p_transfer->channel_number == AUTO_FIND_CHANNEL) {
+ /* check each channel lock,find a free channel... */
+ for (i = 0; i < p_dma->dwc.channel_max_number; i++) {
+ ret_status = axi_dma_trylock(&p_dma->dma_channel[i].channel_lock);
+ if (ret_status == AXI_DMA_RET_OK)
+ break;
+ }
+
+ if (i < p_dma->dwc.channel_max_number) {
+ ret_status = check_channel_real_free(p_dma, i);
+ if (ret_status != CHANNEL_REAL_FREE) {
+ FH_AXI_DMA_PRINT("auto request channel error\n");
+ AXI_DMA_ASSERT(ret_status == CHANNEL_REAL_FREE);
+ }
+ /* caution : channel is already locked here.... */
+ p_transfer->channel_number = i;
+ /* bind to the controller. */
+ /* p_transfer->dma_controller = p_dma; */
+ p_dma->dma_channel[i].channel_status = CHANNEL_STATUS_OPEN;
+ } else {
+ FH_AXI_DMA_PRINT("[dma]: auto request err, no free channel\n");
+ return -AXI_DMA_RET_NO_MEM;
+ }
+ }
+ /* request channel by user */
+ else {
+ AXI_DMA_ASSERT(p_transfer->channel_number < p_dma->dwc.channel_max_number);
+ ret_status = axi_dma_lock(
+ &p_dma->dma_channel[p_transfer->channel_number].channel_lock,
+ AXI_DMA_TICK_PER_SEC * 2);
+ if (ret_status != AXI_DMA_RET_OK) {
+ FH_AXI_DMA_PRINT("[dma]: request %d channel err.\n", p_transfer->channel_number);
+ return -AXI_DMA_RET_NO_MEM;
+ }
+
+ /*enter_critical();*/
+ ret_status = check_channel_real_free(p_dma, p_transfer->channel_number);
+ if (ret_status != CHANNEL_REAL_FREE) {
+ FH_AXI_DMA_PRINT("user request channel error\n");
+ AXI_DMA_ASSERT(ret_status == CHANNEL_REAL_FREE);
+ }
+ /* bind to the controller */
+ /* p_transfer->dma_controller = p_dma; */
+ p_dma->dma_channel[p_transfer->channel_number].channel_status =
+ CHANNEL_STATUS_OPEN;
+ /* exit_critical(); */
+ }
+
+ /* malloc desc for this one channel... */
+ /* fix me.... */
+
+ p_dma->dma_channel[p_transfer->channel_number].allign_malloc =
+ (FH_UINT32)axi_dma_malloc_desc(p_dma->kernel_pri,
+ (p_dma->dma_channel[p_transfer->channel_number].desc_total_no *
+ sizeof(struct axi_dma_lli)) +
+ AXI_DESC_ALLIGN, &p_dma->dma_channel[p_transfer->channel_number].allign_phy);
+
+ if (!p_dma->dma_channel[p_transfer->channel_number].allign_malloc) {
+ /* release channel */
+ FH_AXI_DMA_PRINT("[dma]: no mem to malloc channel%d desc..\n",
+ p_transfer->channel_number);
+ p_dma->dma_channel[p_transfer->channel_number].channel_status =
+ CHANNEL_STATUS_CLOSED;
+ axi_dma_unlock(
+ &p_dma->dma_channel[p_transfer->channel_number].channel_lock);
+ return -AXI_DMA_RET_NO_MEM;
+ }
+
+ p_dma->dma_channel[p_transfer->channel_number].base_lli_phy =
+ p_dma->dma_channel[p_transfer->channel_number].allign_phy;
+ p_dma->dma_channel[p_transfer->channel_number].base_lli =
+ (struct axi_dma_lli *)allign_func(
+ p_dma->dma_channel[p_transfer->channel_number].allign_malloc,
+ AXI_DESC_ALLIGN, &p_dma->dma_channel[p_transfer->channel_number].base_lli_phy);
+
+ if (!p_dma->dma_channel[p_transfer->channel_number].base_lli) {
+ FH_AXI_DMA_PRINT("request desc failed..\n");
+ AXI_DMA_ASSERT(p_dma->dma_channel[p_transfer->channel_number].base_lli !=
+ AXI_DMA_NULL);
+ }
+
+ if ((FH_UINT32)p_dma->dma_channel[p_transfer->channel_number].base_lli %
+ AXI_DESC_ALLIGN) {
+ FH_AXI_DMA_PRINT("malloc is not cache allign..");
+ }
+
+ /* axi_dma_memset((void *)dma_trans_desc->first_lli, 0, lli_size * sizeof(struct */
+ /* axi_dma_lli)); */
+ axi_dma_memset((void *)p_dma->dma_channel[p_transfer->channel_number].base_lli,
+ 0, p_dma->dma_channel[p_transfer->channel_number].desc_total_no *
+ sizeof(struct axi_dma_lli));
+
+ p_dma->dma_channel[p_transfer->channel_number].desc_left_cnt =
+ p_dma->dma_channel[p_transfer->channel_number].desc_total_no;
+ p_dma->dma_channel[p_transfer->channel_number].free_index = 0;
+ p_dma->dma_channel[p_transfer->channel_number].used_index = 0;
+
+
+ return AXI_DMA_RET_OK;
+}
+
+static void fhc_chan_able_set(struct fh_axi_dma *p_dma,
+struct dma_transfer *p_transfer, FH_SINT32 enable)
+{
+ struct dw_axi_dma *temp_dwc;
+ FH_SINT32 ret, ret_read;
+ FH_UINT32 time_out = 0xffffff;
+ FH_UINT32 chan_mask = lift_shift_bit_num(p_transfer->channel_number);
+
+ temp_dwc = &p_dma->dwc;
+ ret = dw_readl(temp_dwc, CHEN_LO);
+ ret &= ~(chan_mask);
+ ret |= enable ? ((chan_mask) | (chan_mask << 8)) : (chan_mask << 8);
+
+ dw_writel(temp_dwc, CHEN_LO, ret);
+ /*enable == 1 do not check. maybe just isr break. the bit dma will self clear*/
+ if (enable == 0) {
+ do {
+ ret_read = dw_readl(temp_dwc, CHEN_LO);
+ time_out--;
+ } while ((!!(ret_read & chan_mask) != enable) && time_out);
+ }
+
+ if (!time_out)
+ dump_chan_xfer_info(p_dma, p_transfer);
+}
+
+static void fhc_chan_susp_set(struct fh_axi_dma *p_dma,
+struct dma_transfer *p_transfer, FH_SINT32 enable)
+{
+ struct dw_axi_dma *temp_dwc;
+ FH_SINT32 ret;
+ FH_UINT32 time_out = 0xffffff;
+ FH_SINT32 chan_no = p_transfer->channel_number;
+ FH_UINT32 chan_mask = lift_shift_bit_num(p_transfer->channel_number);
+
+ temp_dwc = &p_dma->dwc;
+ ret = dw_readl(temp_dwc, CHEN_LO);
+ ret &= ~(chan_mask << 16);
+ ret |= enable ? ((chan_mask << 16) | (chan_mask << 24)) : (chan_mask << 24);
+ dw_writel(temp_dwc, CHEN_LO, ret);
+
+ if (enable) {
+ do {
+ ret = dw_readl(temp_dwc, CHAN[chan_no].INTSTATUS_LO);
+ time_out--;
+ } while ((!!(ret & DWAXIDMAC_IRQ_SUSPENDED) != enable) && time_out);
+
+ if (!time_out) {
+ dump_chan_xfer_info(p_dma, p_transfer);
+ return;
+ }
+ /*clear susp irp*/
+ dw_writel(temp_dwc, CHAN[chan_no].INTCLEAR_LO, DWAXIDMAC_IRQ_SUSPENDED);
+ }
+}
+
+static FH_UINT32 handle_release_channel(struct fh_axi_dma *p_dma,
+struct dma_transfer *p_transfer)
+{
+ FH_UINT32 ret_status;
+ /* enter_critical(); */
+ ret_status = p_dma->dma_channel[p_transfer->channel_number].channel_status;
+
+ AXI_DMA_ASSERT(p_transfer->channel_number < p_dma->dwc.channel_max_number);
+
+ if (ret_status == CHANNEL_STATUS_CLOSED) {
+ FH_AXI_DMA_PRINT(
+ "release channel error,reason: release a closed channel!!\n");
+ AXI_DMA_ASSERT(ret_status != CHANNEL_STATUS_CLOSED);
+ }
+ fhc_chan_able_set(p_dma, p_transfer, 0);
+
+ axi_dma_unlock(
+ &p_dma->dma_channel[p_transfer->channel_number].channel_lock);
+ /* p_transfer->dma_controller = AXI_DMA_NULL; */
+ p_dma->dma_channel[p_transfer->channel_number].channel_status =
+ CHANNEL_STATUS_CLOSED;
+ p_dma->dma_channel[p_transfer->channel_number].open_flag =
+ DEFAULT_TRANSFER;
+ /* exit_critical(); */
+
+ axi_dma_free_desc(p_dma->kernel_pri,
+ p_dma->dma_channel[p_transfer->channel_number].desc_total_no *
+ sizeof(struct axi_dma_lli) + AXI_DESC_ALLIGN,
+ (void *)p_dma->dma_channel[p_transfer->channel_number].allign_malloc,
+ p_dma->dma_channel[p_transfer->channel_number].allign_phy);
+
+ p_dma->dma_channel[p_transfer->channel_number].allign_malloc = AXI_DMA_NULL;
+ p_dma->dma_channel[p_transfer->channel_number].base_lli = AXI_DMA_NULL;
+ p_dma->dma_channel[p_transfer->channel_number].allign_phy = AXI_DMA_NULL;
+ p_dma->dma_channel[p_transfer->channel_number].base_lli_phy = AXI_DMA_NULL;
+
+ p_dma->dma_channel[p_transfer->channel_number].desc_left_cnt =
+ p_dma->dma_channel[p_transfer->channel_number].desc_total_no;
+ p_dma->dma_channel[p_transfer->channel_number].free_index = 0;
+ p_dma->dma_channel[p_transfer->channel_number].used_index = 0;
+
+ return AXI_DMA_RET_OK;
+}
+
+void axi_dma_ctl_init(FH_UINT32 *low, FH_UINT32 *high)
+{
+ /*cache*/
+ *low |= CH_CTL_L_AR_CACHE(3) | CH_CTL_L_AW_CACHE(0);
+ /*burst len*/
+ *high |= CH_CTL_H_ARLEN_EN(1) | CH_CTL_H_ARLEN(0xf) | CH_CTL_H_AWLEN_EN(0) | CH_CTL_H_AWLEN(0xf);
+}
+
+void axi_dma_cfg_init(FH_UINT32 *low, FH_UINT32 *high)
+{
+ /*out standing*/
+ *high |= CH_CFG_H_DST_OSR_LMT(7) | CH_CFG_H_SRC_OSR_LMT(7);
+}
+
+void handle_transfer(struct fh_axi_dma *p_dma,
+struct dma_transfer *p_transfer)
+{
+ FH_UINT32 desc_size;
+ FH_UINT32 i;
+ FH_UINT32 lli_phy_add;
+ FH_UINT32 dst_inc_mode;
+ FH_UINT32 src_inc_mode;
+ FH_UINT32 ret_status;
+ FH_UINT32 cfg_low;
+ FH_UINT32 cfg_high;
+ struct dma_transfer *dma_trans_desc;
+ struct axi_dma_lli *p_lli_base;
+ FH_UINT32 lli_phy_base;
+ struct axi_dma_lli *p_lli = AXI_DMA_NULL;
+ struct dw_axi_dma *temp_dwc;
+ struct dma_transfer_desc *p_head_desc;
+
+ FH_UINT32 isr = DWAXIDMAC_IRQ_DMA_TRF | DWAXIDMAC_IRQ_BLOCK_TRF | DWAXIDMAC_IRQ_SUSPENDED;
+ FH_UINT32 isr_sig = DWAXIDMAC_IRQ_DMA_TRF | DWAXIDMAC_IRQ_BLOCK_TRF;
+
+ dma_trans_desc = p_transfer;
+ temp_dwc = &p_dma->dwc;
+ p_head_desc = p_transfer->p_desc;
+ desc_size = p_transfer->desc_size;
+ p_transfer->dma_controller->dma_channel[p_transfer->channel_number].active_trans = dma_trans_desc;
+
+ dma_trans_desc->first_lli = get_desc(p_dma, p_transfer, desc_size);
+
+ /* not enough mem.. */
+ if (dma_trans_desc->first_lli == AXI_DMA_NULL) {
+ FH_AXI_DMA_PRINT("transfer error,reason: not enough mem..\n");
+ AXI_DMA_ASSERT(dma_trans_desc->first_lli != AXI_DMA_NULL);
+ }
+ axi_dma_invalidate_desc((FH_UINT32)dma_trans_desc->first_lli,
+ desc_size * sizeof(struct axi_dma_lli));
+ axi_dma_memset((void *)dma_trans_desc->first_lli, 0,
+ desc_size * sizeof(struct axi_dma_lli));
+ p_lli = dma_trans_desc->first_lli;
+ lli_phy_base = p_dma->dma_channel[p_transfer->channel_number].base_lli_phy;
+ p_lli_base = p_dma->dma_channel[p_transfer->channel_number].base_lli;
+
+ AXI_DMA_ASSERT(((FH_UINT32)p_lli & AXI_DESC_ALLIGN_BIT_MASK) == 0);
+ for (i = 0; i < desc_size; i++, p_head_desc++) {
+ /*parse each desc*/
+ dst_inc_mode = (p_head_desc->dst_inc_mode == DW_DMA_SLAVE_INC) ? 0 : 1;
+ src_inc_mode = (p_head_desc->src_inc_mode == DW_DMA_SLAVE_INC) ? 0 : 1;
+ p_lli[i].sar_lo = p_head_desc->src_add;
+ p_lli[i].dar_lo = p_head_desc->dst_add;
+ p_lli[i].ctl_lo =
+ AXI_DMA_CTLL_DST_WIDTH(p_head_desc->dst_width) |
+ AXI_DMA_CTLL_SRC_WIDTH(p_head_desc->src_width) |
+ AXI_DMA_CTLL_DST_MSIZE(p_head_desc->dst_msize) |
+ AXI_DMA_CTLL_SRC_MSIZE(p_head_desc->src_msize) |
+ AXI_DMA_CTLL_DST_INC_MODE(dst_inc_mode) |
+ AXI_DMA_CTLL_SRC_INC_MODE(src_inc_mode);
+ p_lli[i].ctl_hi = CH_CTL_H_LLI_VALID;
+ if (p_dma->dma_channel[p_transfer->channel_number].open_flag == CYCLIC_TRANSFER)
+ p_lli[i].ctl_hi |= CH_CTL_H_IOC_BLKTFR;
+
+ axi_dma_ctl_init(&p_lli[i].ctl_lo, &p_lli[i].ctl_hi);
+
+ p_lli[i].block_ts_lo = p_head_desc->size - 1;
+
+ if ((i + 1) < desc_size) {
+ lli_phy_add = vir_lli_to_phy_lli(p_lli_base, lli_phy_base, &p_lli[i + 1]);
+ p_lli[i].llp_lo = lli_phy_add;
+ } else {
+ if (p_dma->dma_channel[p_transfer->channel_number].open_flag == SINGLE_TRANSFER)
+ p_lli[i].ctl_hi |= CH_CTL_H_LLI_LAST;
+ else {
+ /*cyclic make a ring..*/
+ lli_phy_add = vir_lli_to_phy_lli(p_lli_base, lli_phy_base, &p_lli[0]);
+ p_lli[i].llp_lo = lli_phy_add;
+ }
+ }
+ axi_dma_clean_desc((FH_UINT32)&p_lli[i],
+ sizeof(struct axi_dma_lli));
+#ifdef AXI_DMA_DEBUG
+ dump_lli(&p_lli[i], p_lli_base, lli_phy_base);
+#endif
+ }
+
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_LO,
+ 3 << CH_CFG_L_DST_MULTBLK_TYPE_POS | 3 << CH_CFG_L_SRC_MULTBLK_TYPE_POS);
+ /* set flow mode */
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_HI,
+ AXI_DMA_CFGH_FC(dma_trans_desc->fc_mode));
+ /* set base link add */
+ lli_phy_add = vir_lli_to_phy_lli(p_lli_base, lli_phy_base, &p_lli[0]);
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].LLP, lli_phy_add);
+ /* clear isr */
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].INTCLEAR_LO, 0xffffffff);
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].INTCLEAR_HI, 0xffffffff);
+ /* open isr */
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].INTSTATUS_EN_LO, isr);
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].INTSIGNAL_LO, isr_sig);
+ AXI_DMA_ASSERT(dma_trans_desc->dst_hs <= DMA_SW_HANDSHAKING);
+ AXI_DMA_ASSERT(dma_trans_desc->src_hs <= DMA_SW_HANDSHAKING);
+ /* only hw handshaking need this.. */
+ switch (dma_trans_desc->fc_mode) {
+ case DMA_M2M:
+ break;
+ case DMA_M2P:
+ ret_status = dw_readl(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_HI);
+ ret_status &= ~0x18;
+ ret_status |= dma_trans_desc->dst_per << 12;
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_HI, ret_status);
+ break;
+ case DMA_P2M:
+ ret_status = dw_readl(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_HI);
+ ret_status &= ~0x18;
+ ret_status |= dma_trans_desc->src_per << 7;
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_HI, ret_status);
+ break;
+ default:
+ break;
+ }
+
+ /*rewrite cfg..*/
+ cfg_low = dw_readl(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_LO);
+ cfg_high = dw_readl(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_HI);
+ axi_dma_cfg_init(&cfg_low, &cfg_high);
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_LO, cfg_low);
+ dw_writel(temp_dwc, CHAN[dma_trans_desc->channel_number].CFG_HI, cfg_high);
+
+ dma_trans_desc->dma_controller
+ ->dma_channel[dma_trans_desc->channel_number]
+ .channel_status = CHANNEL_STATUS_BUSY;
+
+ if (dma_trans_desc->prepare_callback)
+ dma_trans_desc->prepare_callback(dma_trans_desc->prepare_para);
+
+#ifdef AXI_DMA_DEBUG
+ dump_dma_common_reg(p_dma);
+ dump_channel_reg(p_dma, dma_trans_desc);
+#endif
+ fhc_chan_able_set(p_dma, dma_trans_desc, 1);
+}
+
+static void handle_single_transfer(struct fh_axi_dma *p_dma,
+struct dma_transfer *p_transfer)
+{
+ FH_UINT32 ret_status;
+ axi_dma_list *p_controller_list;
+ FH_UINT32 max_trans_size;
+ struct dma_transfer *dma_trans_desc;
+ struct dma_transfer *_dma_trans_desc;
+
+ AXI_DMA_ASSERT(p_transfer->channel_number < p_dma->dwc.channel_max_number);
+ AXI_DMA_ASSERT(p_transfer->dma_number < DMA_CONTROLLER_NUMBER);
+ /* when the dma transfer....the lock should be 0!!!! */
+ /* or user may not request the channel... */
+
+ ret_status = p_dma->dma_channel[p_transfer->channel_number].channel_status;
+ if (ret_status == CHANNEL_STATUS_CLOSED) {
+ FH_AXI_DMA_PRINT("transfer error,reason: use a closed channel..\n");
+ AXI_DMA_ASSERT(ret_status != CHANNEL_STATUS_CLOSED);
+ }
+ p_transfer->dma_controller = p_dma;
+
+ axi_dma_list_init(&p_transfer->transfer_list);
+ max_trans_size =
+ p_transfer->dma_controller->dma_channel[p_transfer->channel_number]
+ .desc_trans_size;
+ if (p_transfer->period_len != 0)
+ max_trans_size = axi_dma_min(max_trans_size, p_transfer->period_len);
+
+ /* add transfer to the controller's queue list */
+ /* here should insert before and handle after....this could be a fifo... */
+ axi_dma_list_insert_before(&p_dma->dma_channel[p_transfer->channel_number].queue,
+ &p_transfer->transfer_list);
+
+ p_controller_list = &p_dma->dma_channel[p_transfer->channel_number].queue;
+
+ /* here the driver could make a queue to cache the transfer and kick a */
+ /* thread to handle the queue~~~ */
+ /* but now,this is a easy version...,just handle the transfer now!!! */
+ axi_dma_list_for_each_entry_safe(dma_trans_desc, _dma_trans_desc,
+ p_controller_list, transfer_list) {
+ handle_transfer(p_dma, dma_trans_desc);
+ }
+
+}
+
+FH_SINT32 axi_dma_driver_control(struct fh_axi_dma *dma,
+FH_UINT32 cmd, struct dma_transfer *arg)
+{
+ struct fh_axi_dma *my_own = dma;
+ struct dw_axi_dma *temp_dwc = &my_own->dwc;
+ FH_ERR ret = AXI_DMA_RET_OK;
+ struct dma_transfer *p_dma_transfer = arg;
+
+ switch (cmd) {
+ case AXI_DMA_CTRL_DMA_OPEN:
+ /* open the controller.. */
+ handle_dma_open(my_own);
+ break;
+ case AXI_DMA_CTRL_DMA_CLOSE:
+ /* close the controller.. */
+ handle_dma_close(my_own);
+ break;
+ case AXI_DMA_CTRL_DMA_REQUEST_CHANNEL:
+ /* request a channel for the user */
+ ret = handle_request_channel(my_own, p_dma_transfer);
+ break;
+ case AXI_DMA_CTRL_DMA_RELEASE_CHANNEL:
+ /* release a channel */
+ AXI_DMA_ASSERT(p_dma_transfer != AXI_DMA_NULL);
+ ret = handle_release_channel(my_own, p_dma_transfer);
+ break;
+ case AXI_DMA_CTRL_DMA_SINGLE_TRANSFER:
+ /* make a channel to transfer data. */
+ AXI_DMA_ASSERT(p_dma_transfer != AXI_DMA_NULL);
+ /* check if the dma channel is open,or return error. */
+ my_own->dma_channel[p_dma_transfer->channel_number].open_flag =
+ SINGLE_TRANSFER;
+ handle_single_transfer(my_own, p_dma_transfer);
+ /* then wait for the channel is complete.. */
+ /* caution that::we should be in the "enter_critical()"when set the */
+ /* dma to work. */
+ break;
+
+ case AXI_DMA_CTRL_DMA_CYCLIC_PREPARE:
+ AXI_DMA_ASSERT(p_dma_transfer != AXI_DMA_NULL);
+ my_own->dma_channel[p_dma_transfer->channel_number].open_flag =
+ CYCLIC_TRANSFER;
+ fh_axi_dma_cyclic_prep(my_own, p_dma_transfer);
+ break;
+
+ case AXI_DMA_CTRL_DMA_CYCLIC_START:
+ fh_axi_dma_cyclic_start(p_dma_transfer);
+ break;
+
+ case AXI_DMA_CTRL_DMA_CYCLIC_STOP:
+ fh_axi_dma_cyclic_stop(p_dma_transfer);
+ break;
+
+ case AXI_DMA_CTRL_DMA_CYCLIC_FREE:
+ fh_axi_dma_cyclic_free(p_dma_transfer);
+ break;
+ case AXI_DMA_CTRL_DMA_PAUSE:
+ fh_axi_dma_cyclic_pause(p_dma_transfer);
+ break;
+ case AXI_DMA_CTRL_DMA_RESUME:
+ fh_axi_dma_cyclic_resume(p_dma_transfer);
+ break;
+ case AXI_DMA_CTRL_DMA_GET_DAR:
+ return dw_readl(temp_dwc, CHAN[p_dma_transfer->channel_number].DAR);
+ case AXI_DMA_CTRL_DMA_GET_SAR:
+ return dw_readl(temp_dwc, CHAN[p_dma_transfer->channel_number].SAR);
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static void fh_isr_single_process(struct fh_axi_dma *my_own,
+struct dma_transfer *p_transfer)
+{
+ if (p_transfer->isr_prepare_callback)
+ p_transfer->isr_prepare_callback(p_transfer->isr_prepare_para);
+
+ if (p_transfer->complete_callback)
+ p_transfer->complete_callback(p_transfer->complete_para);
+ p_transfer->dma_controller
+ ->dma_channel[p_transfer->channel_number]
+ .channel_status = CHANNEL_STATUS_IDLE;
+ put_desc(my_own, p_transfer);
+ axi_dma_list_remove(&p_transfer->transfer_list);
+}
+
+static void fh_isr_cyclic_process(struct fh_axi_dma *my_own,
+struct dma_transfer *p_transfer)
+{
+ FH_UINT32 index;
+ struct dw_axi_dma *temp_dwc;
+ struct axi_dma_lli *p_lli;
+
+ temp_dwc = &my_own->dwc;
+ p_lli = AXI_DMA_NULL;
+
+ if (p_transfer->isr_prepare_callback)
+ p_transfer->isr_prepare_callback(p_transfer->isr_prepare_para);
+
+ if (p_transfer->complete_callback)
+ p_transfer->complete_callback(p_transfer->complete_para);
+ p_lli = p_transfer->first_lli;
+ /*invaild desc mem to cache...*/
+ axi_dma_invalidate_desc((uint32_t)p_lli,
+ sizeof(struct axi_dma_lli) * p_transfer->cyclic_periods);
+ for (index = 0; index < p_transfer->cyclic_periods; index++) {
+ if (!(p_lli[index].ctl_hi & CH_CTL_H_LLI_VALID))
+ p_lli[index].ctl_hi |= CH_CTL_H_LLI_VALID;
+ }
+ /*flush cache..*/
+ axi_dma_clean_desc((uint32_t)p_lli,
+ sizeof(struct axi_dma_lli) * p_transfer->cyclic_periods);
+ /*kick dma again.*/
+ dw_writel(temp_dwc, CHAN[p_transfer->channel_number].BLK_TFR_RESU, 1);
+}
+
+static void dma_channel_isr_enable(struct dw_axi_dma *dwc, int chan, int val)
+{
+ dw_writel(dwc, CHAN[chan].INTSIGNAL_LO, val);
+}
+
+static int dma_channel_isr_disable(struct dw_axi_dma *dwc, int chan)
+{
+ int raw = dw_readl(dwc, CHAN[chan].INTSIGNAL_LO);
+
+ dw_writel(dwc, CHAN[chan].INTSIGNAL_LO, 0);
+ return raw;
+}
+
+void fh_axi_dma_isr_enable_set(struct fh_axi_dma *param, FH_UINT32 enable)
+{
+ struct fh_axi_dma *my_own = param;
+ struct dw_axi_dma *temp_dwc = &my_own->dwc;
+ FH_UINT32 i;
+
+ /* enable channel int */
+ for (i = 0; i < my_own->dwc.channel_max_number; i++) {
+ if (enable) {
+ int int_sig = my_own->dma_channel[i].int_sig;
+
+ if (int_sig) {
+ dma_channel_isr_enable(temp_dwc, i, int_sig);
+ my_own->dma_channel[i].int_sig = 0;
+ }
+ } else {
+ int status = dw_readl(temp_dwc, CHAN[i].INTSTATUS_LO)
+ & (~DWAXIDMAC_IRQ_SUSPENDED);
+ if (!status)
+ continue;
+ /* backup channel int, then disable it */
+ my_own->dma_channel[i].status = status;
+ my_own->dma_channel[i].int_sig =
+ dma_channel_isr_disable(temp_dwc, i);
+ /* clear int */
+ dw_writel(temp_dwc, CHAN[i].INTCLEAR_LO, status);
+ if (status & DWAXIDMAC_IRQ_ALL_ERR) {
+ FH_AXI_DMA_PRINT("bug status is %x\n", status);
+ AXI_DMA_ASSERT(0);
+ }
+ }
+ }
+}
+
+void fh_axi_dma_isr(struct fh_axi_dma *param)
+{
+ FH_UINT32 status;
+ FH_UINT32 i;
+ struct dw_axi_dma *temp_dwc;
+ struct fh_axi_dma *my_own = param;
+ temp_dwc = &my_own->dwc;
+
+ for (i = 0; i < my_own->dwc.channel_max_number; i++) {
+ if (!my_own->dma_channel[i].status)
+ continue;
+ status = my_own->dma_channel[i].status;
+ if (my_own->dma_channel[i].open_flag == SINGLE_TRANSFER) {
+ if (status & DWAXIDMAC_IRQ_DMA_TRF) {
+ fh_isr_single_process(my_own,
+ my_own->dma_channel[i].active_trans);
+ }
+ }
+ if (my_own->dma_channel[i].open_flag == CYCLIC_TRANSFER) {
+ if (status & DWAXIDMAC_IRQ_BLOCK_TRF) {
+ fh_isr_cyclic_process(my_own,
+ my_own->dma_channel[i].active_trans);
+ }
+ }
+ my_own->dma_channel[i].status = 0;
+ }
+}
+
+const char *channel_lock_name[AXI_DMA_MAX_NR_CHANNELS] = {
+ "channel_0_lock", "channel_1_lock", "channel_2_lock", "channel_3_lock",
+ "channel_4_lock", "channel_5_lock", "channel_6_lock", "channel_7_lock",
+};
+
+static void fh_axi_dma_cyclic_pause(struct dma_transfer *p)
+{
+ struct fh_axi_dma *my_own = p->dma_controller;
+
+ fhc_chan_susp_set(my_own, p, 1);
+}
+
+static void fh_axi_dma_cyclic_resume(struct dma_transfer *p)
+{
+ struct fh_axi_dma *my_own = p->dma_controller;
+
+ fhc_chan_susp_set(my_own, p, 0);
+}
+
+static void fh_axi_dma_cyclic_stop(struct dma_transfer *p)
+{
+ struct fh_axi_dma *my_own = p->dma_controller;
+
+ fhc_chan_susp_set(my_own, p, 1);
+ fhc_chan_able_set(my_own, p, 0);
+}
+
+static void fh_axi_dma_cyclic_start(struct dma_transfer *p)
+{
+ struct fh_axi_dma *my_own = p->dma_controller;
+ struct dw_axi_dma *dwc;
+ struct axi_dma_lli *p_lli = AXI_DMA_NULL;
+
+ dwc = &my_own->dwc;
+ p_lli = p->first_lli;
+
+ /* warnning!!!!must check if the add is 64Byte ally... */
+ AXI_DMA_ASSERT(((FH_UINT32)p_lli & AXI_DESC_ALLIGN_BIT_MASK) == 0);
+ handle_transfer(my_own, p);
+}
+
+static void fh_axi_dma_cyclic_prep(struct fh_axi_dma *fh_dma_p,
+struct dma_transfer *p)
+{
+ /* bind the controller to the transfer */
+ p->dma_controller = fh_dma_p;
+ /* bind active transfer */
+ fh_dma_p->dma_channel[p->channel_number].active_trans = p;
+}
+
+static void fh_axi_dma_cyclic_free(struct dma_transfer *p)
+{
+ struct fh_axi_dma *my_own = p->dma_controller;
+
+ put_desc(my_own, p);
+}
+
+FH_UINT32 cal_axi_dma_channel(void *regs)
+{
+#ifdef DMA_FIXED_CHANNEL_NUM
+ return DMA_FIXED_CHANNEL_NUM;
+#else
+ FH_UINT32 ret;
+ FH_UINT32 i;
+ FH_UINT32 time_out = 0xffffff;
+
+ /*reset first..*/
+ __dma_raw_writel(1, &(((struct dw_axi_dma_regs *)regs)->RESET));
+ do {
+ ret = __dma_raw_readl(&(((struct dw_axi_dma_regs *)regs)->RESET));
+ time_out--;
+ } while (ret && time_out);
+
+ if (!time_out)
+ FH_AXI_DMA_PRINT("%s :: %d : time out..\n", __func__, __LINE__);
+ time_out = 0xffffff;
+ /*enable dma.*/
+ __dma_raw_writel(1, &(((struct dw_axi_dma_regs *)regs)->CFG));
+
+ /*write channel.*/
+ for (i = 0; i < AXI_DMA_MAX_NR_CHANNELS; i++) {
+ __dma_raw_writel(1 << i | 1 << (8+i), &(((struct dw_axi_dma_regs *)regs)->CHEN_LO));
+ ret = __dma_raw_readl(&(((struct dw_axi_dma_regs *)regs)->CHEN_LO));
+ if (ret < 1 << i)
+ break;
+ }
+
+ /*reset again*/
+ __dma_raw_writel(1, &(((struct dw_axi_dma_regs *)regs)->RESET));
+ do {
+ ret = __dma_raw_readl(&(((struct dw_axi_dma_regs *)regs)->RESET));
+ time_out--;
+ } while (ret && time_out);
+
+ if (!time_out)
+ FH_AXI_DMA_PRINT("%s :: %d : time out..\n", __func__, __LINE__);
+
+ return i;
+#endif
+}
+
+
+struct axi_dma_ops *get_fh_axi_dma_ops(struct fh_axi_dma *p_axi_dma)
+{
+ AXI_DMA_ASSERT(p_axi_dma != AXI_DMA_NULL);
+ return &p_axi_dma->ops;
+}
+
+
+void get_desc_para(struct fh_axi_dma *dma, struct dma_transfer *p_transfer,
+FH_UINT32 *desc_size, FH_UINT32 *base_phy_add,
+FH_UINT32 *each_desc_size, FH_UINT32 *each_desc_cap)
+{
+ *desc_size = dma->dma_channel[p_transfer->channel_number]
+ .desc_total_no;
+ *base_phy_add = dma->dma_channel[p_transfer->channel_number]
+ .base_lli_phy;
+ *each_desc_size = sizeof(struct axi_dma_lli);
+ *each_desc_cap = dma->dma_channel[p_transfer->channel_number]
+ .desc_trans_size;
+}
+
+struct fh_axi_dma *fh_axi_dma_probe(struct axi_dma_platform_data *priv_data)
+{
+ FH_UINT32 i;
+ struct fh_axi_dma *fh_dma_p;
+ struct axi_dma_platform_data *plat = priv_data;
+
+ fh_dma_p = (struct fh_axi_dma *)axi_dma_malloc(sizeof(struct fh_axi_dma));
+ if (!fh_dma_p) {
+ FH_AXI_DMA_PRINT("ERROR: %s, malloc failed\n", __func__);
+ return AXI_DMA_NULL;
+ }
+ axi_dma_memset(fh_dma_p, 0, sizeof(struct fh_axi_dma));
+ axi_dma_scanf(fh_dma_p->dwc.name, "%s%d",
+ plat->name, (FH_SINT32)plat->id);
+
+ fh_dma_p->dwc.regs = (void *)plat->base;
+ fh_dma_p->dwc.channel_max_number =
+ cal_axi_dma_channel(fh_dma_p->dwc.regs);
+ fh_dma_p->dwc.controller_status = CONTROLLER_STATUS_CLOSED;
+ fh_dma_p->dwc.id = plat->id;
+ fh_dma_p->kernel_pri = plat->kernel_pri;
+ fh_dma_p->adapt_pri = plat->adapt_pri;
+ fh_dma_p->ops.axi_dma_isr_process = fh_axi_dma_isr;
+ fh_dma_p->ops.axi_dma_control = axi_dma_driver_control;
+ fh_dma_p->ops.axi_dma_get_desc_para = get_desc_para;
+ fh_dma_p->ops.axi_dma_isr_enable_set = fh_axi_dma_isr_enable_set;
+
+ /* channel set */
+ for (i = 0; i < fh_dma_p->dwc.channel_max_number; i++) {
+ fh_dma_p->dma_channel[i].channel_status = CHANNEL_STATUS_CLOSED;
+ fh_dma_p->dma_channel[i].desc_total_no = DESC_MAX_SIZE;
+ fh_dma_p->dma_channel[i].int_sig = 0;
+ fh_dma_p->dma_channel[i].status = 0;
+ axi_dma_list_init(&(fh_dma_p->dma_channel[i].queue));
+ fh_dma_p->dma_channel[i].desc_trans_size =
+ FH_CHANNEL_MAX_TRANSFER_SIZE;
+ axi_dma_lock_init(&fh_dma_p->dma_channel[i].channel_lock,
+ channel_lock_name[i]);
+ }
+ return fh_dma_p;
+}
diff --git a/drivers/dma/fh_dmac.c b/drivers/dma/fh_dmac.c
new file mode 100644
index 00000000..7c985173
--- /dev/null
+++ b/drivers/dma/fh_dmac.c
@@ -0,0 +1,2101 @@
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include "dmaengine.h"
+#include <mach/fh_dma_plat.h>
+#include <linux/fh_dmac.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+
+#define FH_DMA_MAX_NR_CHANNELS 8
+#define FH_DMA_MAX_NR_REQUESTS 16
+
+/* Platform-configurable bits in CFG_LO */
+#define FHC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */
+#define FHC_CFGL_LOCK_CH_BLOCK (1 << 12)
+#define FHC_CFGL_LOCK_CH_XACT (2 << 12)
+#define FHC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */
+#define FHC_CFGL_LOCK_BUS_BLOCK (1 << 14)
+#define FHC_CFGL_LOCK_BUS_XACT (2 << 14)
+#define FHC_CFGL_LOCK_CH (1 << 15) /* channel lockout */
+#define FHC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */
+#define FHC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */
+#define FHC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */
+
+/* Bitfields in FH_PARAMS */
+#define FH_PARAMS_NR_CHAN 8 /* number of channels */
+#define FH_PARAMS_NR_MASTER 11 /* number of AHB masters */
+#define FH_PARAMS_DATA_WIDTH(n) (15 + 2 * (n))
+#define FH_PARAMS_DATA_WIDTH1 15 /* master 1 data width */
+#define FH_PARAMS_DATA_WIDTH2 17 /* master 2 data width */
+#define FH_PARAMS_DATA_WIDTH3 19 /* master 3 data width */
+#define FH_PARAMS_DATA_WIDTH4 21 /* master 4 data width */
+#define FH_PARAMS_EN 28 /* encoded parameters */
+
+/* Bitfields in FHC_PARAMS */
+#define FHC_PARAMS_MBLK_EN 11 /* multi block transfer */
+
+/* Bitfields in CTL_LO */
+#define FHC_CTLL_INT_EN (1 << 0) /* irqs enabled? */
+#define FHC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */
+#define FHC_CTLL_SRC_WIDTH(n) ((n)<<4)
+#define FHC_CTLL_DST_INC (0<<7) /* DAR update/not */
+#define FHC_CTLL_DST_DEC (1<<7)
+#define FHC_CTLL_DST_FIX (2<<7)
+#define FHC_CTLL_SRC_INC (0<<9) /* SAR update/not */
+#define FHC_CTLL_SRC_DEC (1<<9)
+#define FHC_CTLL_SRC_FIX (2<<9)
+#define FHC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */
+#define FHC_CTLL_SRC_MSIZE(n) ((n)<<14)
+#define FHC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */
+#define FHC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */
+#define FHC_CTLL_FC(n) ((n) << 20)
+#define FHC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */
+#define FHC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */
+#define FHC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */
+#define FHC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */
+/* plus 4 transfer types for peripheral-as-flow-controller */
+#define FHC_CTLL_DMS(n) ((n)<<23) /* dst master select */
+#define FHC_CTLL_SMS(n) ((n)<<25) /* src master select */
+#define FHC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */
+#define FHC_CTLL_LLP_S_EN (1 << 28) /* src block chain */
+
+/* Bitfields in CTL_HI */
+#define FHC_CTLH_DONE 0x00001000
+#define FHC_CTLH_BLOCK_TS_MASK 0x00000fff
+#define FHC_PROTCTL_MASK (7 << 2)
+#define FHC_PROTCTL(n) ((n) << 2)
+/* Bitfields in CFG_LO. Platform-configurable bits are in <linux/fh_dmac.h> */
+#define FHC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */
+#define FHC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */
+#define FHC_CFGL_CH_SUSP (1 << 8) /* pause xfer */
+#define FHC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */
+#define FHC_CFGL_HS_DST (1 << 10) /* handshake w/dst */
+#define FHC_CFGL_HS_SRC (1 << 11) /* handshake w/src */
+#define FHC_CFGL_MAX_BURST(x) ((x) << 20)
+#define FHC_CFGL_RELOAD_SAR (1 << 30)
+#define FHC_CFGL_RELOAD_DAR (1 << 31)
+
+/* Bitfields in CFG_HI. Platform-configurable bits are in <linux/fh_dmac.h> */
+#define FHC_CFGH_DS_UPD_EN (1 << 5)
+#define FHC_CFGH_SS_UPD_EN (1 << 6)
+
+/* Bitfields in SGR */
+#define FHC_SGR_SGI(x) ((x) << 0)
+#define FHC_SGR_SGC(x) ((x) << 20)
+
+/* Bitfields in DSR */
+#define FHC_DSR_DSI(x) ((x) << 0)
+#define FHC_DSR_DSC(x) ((x) << 20)
+
+/* Bitfields in CFG */
+#define FH_CFG_DMA_EN (1 << 0)
+
+#define FH_REGLEN 0x400
+#define PROTCTL_ENABLE 0x55
+#define MASTER_SEL_ENABLE 0x55
+
+/*
+ * Redefine this macro to handle differences between 32- and 64-bit
+ * addressing, big vs. little endian, etc.
+ */
+#define FH_REG(name) u32 name; u32 __pad_##name
+
+/* Hardware register definitions. */
+struct fh_dma_chan_regs {
+ FH_REG(SAR); /* Source Address Register */
+ FH_REG(DAR); /* Destination Address Register */
+ FH_REG(LLP); /* Linked List Pointer */
+ u32 CTL_LO; /* Control Register Low */
+ u32 CTL_HI; /* Control Register High */
+ FH_REG(SSTAT);
+ FH_REG(DSTAT);
+ FH_REG(SSTATAR);
+ FH_REG(DSTATAR);
+ u32 CFG_LO; /* Configuration Register Low */
+ u32 CFG_HI; /* Configuration Register High */
+ FH_REG(SGR);
+ FH_REG(DSR);
+};
+
+struct fh_dma_irq_regs {
+ FH_REG(XFER);
+ FH_REG(BLOCK);
+ FH_REG(SRC_TRAN);
+ FH_REG(DST_TRAN);
+ FH_REG(ERROR);
+};
+
+struct fh_dma_regs {
+ /* per-channel registers */
+ struct fh_dma_chan_regs CHAN[FH_DMA_MAX_NR_CHANNELS];
+
+ /* irq handling */
+ struct fh_dma_irq_regs RAW; /* r */
+ struct fh_dma_irq_regs STATUS; /* r (raw & mask) */
+ struct fh_dma_irq_regs MASK; /* rw (set = irq enabled) */
+ struct fh_dma_irq_regs CLEAR; /* w (ack, affects "raw") */
+
+ FH_REG(STATUS_INT); /* r */
+
+ /* software handshaking */
+ FH_REG(REQ_SRC);
+ FH_REG(REQ_DST);
+ FH_REG(SGL_REQ_SRC);
+ FH_REG(SGL_REQ_DST);
+ FH_REG(LAST_SRC);
+ FH_REG(LAST_DST);
+
+ /* miscellaneous */
+ FH_REG(CFG);
+ FH_REG(CH_EN);
+ FH_REG(ID);
+ FH_REG(TEST);
+
+ /* reserved */
+ FH_REG(__reserved0);
+ FH_REG(__reserved1);
+
+ /* optional encoded params, 0x3c8..0x3f7 */
+ u32 __reserved;
+
+ /* per-channel configuration registers */
+ u32 FHC_PARAMS[FH_DMA_MAX_NR_CHANNELS];
+ u32 MULTI_BLK_TYPE;
+ u32 MAX_BLK_SIZE;
+
+ /* top-level parameters */
+ u32 FH_PARAMS;
+};
+
+/* To access the registers in early stage of probe */
+#define dma_read_byaddr(addr, name) \
+ dma_readl_native((addr) + offsetof(struct fh_dma_regs, name))
+
+#define channel_readl(fhc, name) \
+ dma_readl_native(&(__fhc_regs(fhc)->name))
+#define channel_writel(fhc, name, val) \
+ dma_writel_native((val), &(__fhc_regs(fhc)->name))
+
+#define dma_readl(dw, name) \
+ dma_readl_native(&(__fh_regs(dw)->name))
+#define dma_writel(dw, name, val) \
+ dma_writel_native((val), &(__fh_regs(dw)->name))
+
+#define channel_set_bit(dw, reg, mask) \
+ dma_writel(dw, reg, ((mask) << 8) | (mask))
+#define channel_clear_bit(dw, reg, mask) \
+ dma_writel(dw, reg, ((mask) << 8) | 0)
+
+#define dma_readl_native readl
+#define dma_writel_native writel
+
+static inline struct fh_dma_chan_regs __iomem *
+__fhc_regs(struct fh_dma_chan *fhc)
+{
+ return fhc->ch_regs;
+}
+static inline struct fh_dma_regs __iomem *__fh_regs(struct fh_dma *dw)
+{
+ return dw->regs;
+}
+
+static inline unsigned int fhc_get_dms(struct fh_dma_slave *slave)
+{
+#ifdef CONFIG_ARCH_FHYG
+ return slave ? slave->dst_master : 0;
+#else
+ return slave ? slave->dst_master : 1;
+#endif
+}
+
+static inline unsigned int fhc_get_sms(struct fh_dma_slave *slave)
+{
+#ifdef CONFIG_ARCH_FHYG
+ return slave ? slave->src_master : 0;
+#else
+ return slave ? slave->src_master : 1;
+#endif
+}
+
+static inline void fhc_set_masters(struct fh_dma_chan *fhc)
+{
+ struct fh_dma *fhd = to_fh_dma(fhc->chan.device);
+ struct fh_dma_slave *dms = fhc->chan.private;
+ unsigned char mmax = fhd->nr_masters - 1;
+
+ if (fhc->request_line == ~0) {
+ fhc->src_master = min_t(unsigned char, mmax, fhc_get_sms(dms));
+ fhc->dst_master = min_t(unsigned char, mmax, fhc_get_dms(dms));
+ }
+}
+
+#define FHC_DEFAULT_CTLLO(_chan) ({ \
+ struct fh_dma_chan *_fhc = to_fh_dma_chan(_chan); \
+ struct dma_slave_config *_sconfig = &_fhc->dma_sconfig; \
+ bool _is_slave = is_slave_direction(_fhc->direction); \
+ u8 _smsize = _is_slave ? _sconfig->src_maxburst : \
+ FH_DMA_MSIZE_16; \
+ u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \
+ FH_DMA_MSIZE_16; \
+ \
+ (FHC_CTLL_DST_MSIZE(_dmsize) \
+ | FHC_CTLL_SRC_MSIZE(_smsize) \
+ | FHC_CTLL_LLP_D_EN \
+ | FHC_CTLL_LLP_S_EN \
+ | FHC_CTLL_DMS(_fhc->dst_master) \
+ | FHC_CTLL_SMS(_fhc->src_master)); \
+ })
+
+#define FHC_DEFAULT_CTLLO_OLD(private) ({ \
+ struct fh_dma_slave *__slave = (private); \
+ int dms = __slave ? __slave->dst_master : 0; \
+ int sms = __slave ? __slave->src_master : 0; \
+ u8 smsize = __slave ? __slave->src_msize : FH_DMA_MSIZE_16; \
+ u8 dmsize = __slave ? __slave->dst_msize : FH_DMA_MSIZE_16; \
+ \
+ (FHC_CTLL_DST_MSIZE(dmsize) \
+ | FHC_CTLL_SRC_MSIZE(smsize) \
+ | FHC_CTLL_LLP_D_EN \
+ | FHC_CTLL_LLP_S_EN \
+ | FHC_CTLL_DMS(dms) \
+ | FHC_CTLL_SMS(sms)); \
+ })
+
+/*
+ * Number of descriptors to allocate for each channel. This should be
+ * made configurable somehow; preferably, the clients (at least the
+ * ones using slave transfers) should be able to give us a hint.
+ */
+#ifdef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+#define NR_DESCS_PER_CHANNEL CONFIG_CHANNEL_ALLOC_DESC_NUM
+#else
+#define NR_DESCS_PER_CHANNEL 4096
+#endif
+
+
+/*----------------------------------------------------------------------*/
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+ return &chan->dev->device;
+}
+static struct device *chan2parent(struct dma_chan *chan)
+{
+ return chan->dev->device.parent;
+}
+
+static struct fh_desc *fhc_first_active(struct fh_dma_chan *fhc)
+{
+ return to_fh_desc(fhc->active_list.next);
+}
+
+static struct fh_desc *fhc_desc_get(struct fh_dma_chan *fhc)
+{
+ struct fh_desc *desc, *_desc;
+ struct fh_desc *ret = NULL;
+ unsigned int i = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ list_for_each_entry_safe(desc, _desc, &fhc->free_list, desc_node) {
+ i++;
+ if (async_tx_test_ack(&desc->txd)) {
+ list_del(&desc->desc_node);
+ ret = desc;
+ break;
+ }
+ dev_dbg(chan2dev(&fhc->chan), "desc %p not ACKed\n", desc);
+ }
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ dev_vdbg(chan2dev(&fhc->chan), "scanned %u descriptors on freelist\n", i);
+
+ return ret;
+}
+
+/*
+ * Move a descriptor, including any children, to the free list.
+ * `desc' must not be on any lists.
+ */
+static void fhc_desc_put(struct fh_dma_chan *fhc, struct fh_desc *desc)
+{
+ unsigned long flags;
+
+ if (desc) {
+ struct fh_desc *child;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ list_for_each_entry(child, &desc->tx_list, desc_node)
+ dev_vdbg(chan2dev(&fhc->chan),
+ "moving child desc %p to freelist\n",
+ child);
+ list_splice_init(&desc->tx_list, &fhc->free_list);
+ dev_vdbg(chan2dev(&fhc->chan), "moving desc %p to freelist\n", desc);
+ list_add(&desc->desc_node, &fhc->free_list);
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ }
+}
+
+static void fhc_initialize(struct fh_dma_chan *fhc)
+{
+ struct fh_dma *fhd = to_fh_dma(fhc->chan.device);
+ struct fh_dma_slave *dms = fhc->chan.private;
+ u32 cfghi = FHC_CFGH_FIFO_MODE;
+ u32 cfglo = FHC_CFGL_CH_PRIOR(fhc->priority);
+ struct fh_dma_extra *ext_para = &fhc->ext_para;
+
+ if (fhc->initialized == true)
+ return;
+
+ if (dms) {
+ cfghi = dms->cfg_hi;
+ cfglo |= dms->cfg_lo & ~FHC_CFGL_CH_PRIOR_MASK;
+ } else {
+ if (fhc->direction == DMA_MEM_TO_DEV) {
+ cfghi = FHC_CFGH_DST_PER(fhc->request_line);
+ if (ext_para->protctl_flag == PROTCTL_ENABLE) {
+ cfghi &= ~FHC_PROTCTL_MASK;
+ cfghi |= FHC_PROTCTL(ext_para->protctl_data);
+ }
+ } else if (fhc->direction == DMA_DEV_TO_MEM) {
+ cfghi = FHC_CFGH_SRC_PER(fhc->request_line);
+ if (ext_para->protctl_flag == PROTCTL_ENABLE) {
+ cfghi &= ~FHC_PROTCTL_MASK;
+ cfghi |= FHC_PROTCTL(ext_para->protctl_data);
+ }
+ } else if (fhc->direction == DMA_MEM_TO_MEM) {
+ cfghi &= ~FHC_PROTCTL_MASK;
+ cfghi |= FHC_PROTCTL(2);
+ }
+ }
+ channel_writel(fhc, CFG_LO, cfglo);
+ channel_writel(fhc, CFG_HI, cfghi);
+
+ /* Enable interrupts */
+ channel_set_bit(fhd, MASK.XFER, fhc->mask);
+ channel_set_bit(fhd, MASK.BLOCK, fhc->mask);
+ channel_set_bit(fhd, MASK.ERROR, fhc->mask);
+
+ fhc->initialized = true;
+}
+
+/*----------------------------------------------------------------------*/
+
+static inline unsigned int fhc_fast_fls(unsigned long long v)
+{
+ /*
+ * We can be a lot more clever here, but this should take care
+ * of the most common optimization.
+ */
+ if (!(v & 7))
+ return 3;
+ else if (!(v & 3))
+ return 2;
+ else if (!(v & 1))
+ return 1;
+ return 0;
+}
+
+static inline void fhc_dump_chan_regs(struct fh_dma_chan *fhc)
+{
+ dev_err(chan2dev(&fhc->chan),
+ " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n",
+ channel_readl(fhc, SAR),
+ channel_readl(fhc, DAR),
+ channel_readl(fhc, LLP),
+ channel_readl(fhc, CTL_HI),
+ channel_readl(fhc, CTL_LO));
+}
+
+static inline void fhc_chan_disable(struct fh_dma *fhd, struct fh_dma_chan *fhc)
+{
+ channel_clear_bit(fhd, CH_EN, fhc->mask);
+ while (dma_readl(fhd, CH_EN) & fhc->mask)
+ cpu_relax();
+}
+
+/*----------------------------------------------------------------------*/
+
+/* Perform single block transfer */
+static inline void fhc_do_single_block(struct fh_dma_chan *fhc,
+ struct fh_desc *desc)
+{
+ struct fh_dma *fhd = to_fh_dma(fhc->chan.device);
+ u32 ctllo;
+
+ /* Software emulation of LLP mode relies on interrupts to continue
+ * multi block transfer. */
+ ctllo = desc->lli.ctllo | FHC_CTLL_INT_EN;
+
+ channel_writel(fhc, SAR, desc->lli.sar);
+ channel_writel(fhc, DAR, desc->lli.dar);
+ channel_writel(fhc, CTL_LO, ctllo);
+ channel_writel(fhc, CTL_HI, desc->lli.ctlhi);
+ channel_set_bit(fhd, CH_EN, fhc->mask);
+
+ /* Move pointer to next descriptor */
+ fhc->tx_node_active = fhc->tx_node_active->next;
+}
+
+/* Called with fhc->lock held and bh disabled */
+static void fhc_dostart(struct fh_dma_chan *fhc, struct fh_desc *first)
+{
+ struct fh_dma *fhd = to_fh_dma(fhc->chan.device);
+ unsigned long was_soft_llp;
+
+ /* ASSERT: channel is idle */
+ if (dma_readl(fhd, CH_EN) & fhc->mask) {
+ dev_err(chan2dev(&fhc->chan),
+ "BUG: Attempted to start non-idle channel\n");
+ fhc_dump_chan_regs(fhc);
+
+ /* The tasklet will hopefully advance the queue... */
+ return;
+ }
+
+ if (fhc->nollp) {
+ was_soft_llp = test_and_set_bit(FH_DMA_IS_SOFT_LLP,
+ &fhc->flags);
+ if (was_soft_llp) {
+ dev_err(chan2dev(&fhc->chan),
+ "BUG: Attempted to start new LLP transfer "
+ "inside ongoing one\n");
+ return;
+ }
+
+ fhc_initialize(fhc);
+
+ fhc->residue = first->total_len;
+ fhc->tx_node_active = &first->tx_list;
+
+ /* Submit first block */
+ fhc_do_single_block(fhc, first);
+
+ return;
+ }
+
+ fhc_initialize(fhc);
+
+ channel_writel(fhc, LLP, first->txd.phys);
+ channel_writel(fhc, CTL_LO,
+ FHC_CTLL_LLP_D_EN | FHC_CTLL_LLP_S_EN);
+ channel_writel(fhc, CTL_HI, 0);
+ channel_set_bit(fhd, CH_EN, fhc->mask);
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+fhc_descriptor_complete(struct fh_dma_chan *fhc, struct fh_desc *desc,
+ bool callback_required)
+{
+ dma_async_tx_callback callback = NULL;
+ void *param = NULL;
+ struct dma_async_tx_descriptor *txd = &desc->txd;
+ struct fh_desc *child;
+ unsigned long flags;
+
+ dev_vdbg(chan2dev(&fhc->chan), "descriptor %u complete\n", txd->cookie);
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ dma_cookie_complete(txd);
+ if (callback_required) {
+ callback = txd->callback;
+ param = txd->callback_param;
+ }
+
+ /* async_tx_ack */
+ list_for_each_entry(child, &desc->tx_list, desc_node)
+ async_tx_ack(&child->txd);
+ async_tx_ack(&desc->txd);
+
+ list_splice_init(&desc->tx_list, &fhc->free_list);
+ list_move(&desc->desc_node, &fhc->free_list);
+
+ dma_descriptor_unmap(txd);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ if (callback)
+ callback(param);
+}
+
+static void fhc_complete_all(struct fh_dma *fhd, struct fh_dma_chan *fhc)
+{
+ struct fh_desc *desc, *_desc;
+ LIST_HEAD(list);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ if (dma_readl(fhd, CH_EN) & fhc->mask) {
+ dev_err(chan2dev(&fhc->chan),
+ "BUG: XFER bit set, but channel not idle!\n");
+
+ /* Try to continue after resetting the channel... */
+ fhc_chan_disable(fhd, fhc);
+ }
+
+ /*
+ * Submit queued descriptors ASAP, i.e. before we go through
+ * the completed ones.
+ */
+ list_splice_init(&fhc->active_list, &list);
+ if (!list_empty(&fhc->queue)) {
+ list_move(fhc->queue.next, &fhc->active_list);
+ fhc_dostart(fhc, fhc_first_active(fhc));
+ }
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ fhc_descriptor_complete(fhc, desc, true);
+}
+
+/* Returns how many bytes were already received from source */
+static inline u32 fhc_get_sent(struct fh_dma_chan *fhc)
+{
+ u32 ctlhi = channel_readl(fhc, CTL_HI);
+ u32 ctllo = channel_readl(fhc, CTL_LO);
+
+ return (ctlhi & FHC_CTLH_BLOCK_TS_MASK) * (1 << (ctllo >> 4 & 7));
+}
+
+static void fhc_scan_descriptors(struct fh_dma *fhd, struct fh_dma_chan *fhc)
+{
+ dma_addr_t llp;
+ struct fh_desc *desc, *_desc;
+ struct fh_desc *child;
+ u32 status_xfer;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ /*
+ * Clear block interrupt flag before scanning so that we don't
+ * miss any, and read LLP before RAW_XFER to ensure it is
+ * valid if we decide to scan the list.
+ */
+ dma_writel(fhd, CLEAR.BLOCK, fhc->mask);
+ llp = channel_readl(fhc, LLP);
+ status_xfer = dma_readl(fhd, RAW.XFER);
+
+ if (status_xfer & fhc->mask) {
+ /* Everything we've submitted is done */
+ dma_writel(fhd, CLEAR.XFER, fhc->mask);
+ if (test_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags)) {
+ struct list_head *head, *active = fhc->tx_node_active;
+
+ /*
+ * We are inside first active descriptor.
+ * Otherwise something is really wrong.
+ */
+ desc = fhc_first_active(fhc);
+
+ head = &desc->tx_list;
+ if (active != head) {
+ /* Update desc to reflect last sent one */
+ if (active != head->next)
+ desc = to_fh_desc(active->prev);
+
+ fhc->residue -= desc->len;
+
+ child = to_fh_desc(active);
+
+ /* Submit next block */
+ fhc_do_single_block(fhc, child);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return;
+ }
+
+ /* We are done here */
+ clear_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags);
+ }
+ fhc->residue = 0;
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ fhc_complete_all(fhd, fhc);
+ return;
+ }
+
+ if (list_empty(&fhc->active_list)) {
+ fhc->residue = 0;
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return;
+ }
+
+ if (test_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags)) {
+ dev_vdbg(chan2dev(&fhc->chan), "%s: soft LLP mode\n", __func__);
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return;
+ }
+
+ dev_vdbg(chan2dev(&fhc->chan), "%s: llp=0x%llx\n", __func__,
+ (unsigned long long)llp);
+
+ list_for_each_entry_safe(desc, _desc, &fhc->active_list, desc_node) {
+ /* Initial residue value */
+ fhc->residue = desc->total_len;
+
+ /* Check first descriptors addr */
+ if (desc->txd.phys == llp) {
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return;
+ }
+
+ /* Check first descriptors llp */
+ if (desc->lli.llp == llp) {
+ /* This one is currently in progress */
+ fhc->residue -= fhc_get_sent(fhc);
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return;
+ }
+
+ fhc->residue -= desc->len;
+ list_for_each_entry(child, &desc->tx_list, desc_node) {
+ if (child->lli.llp == llp) {
+ /* Currently in progress */
+ fhc->residue -= fhc_get_sent(fhc);
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return;
+ }
+ fhc->residue -= child->len;
+ }
+
+ /*
+ * No descriptors so far seem to be in progress, i.e.
+ * this one must be done.
+ */
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ fhc_descriptor_complete(fhc, desc, true);
+ spin_lock_irqsave(&fhc->lock, flags);
+ }
+
+ dev_err(chan2dev(&fhc->chan),
+ "BUG: All descriptors done, but channel not idle!\n");
+
+ /* Try to continue after resetting the channel... */
+ fhc_chan_disable(fhd, fhc);
+
+ if (!list_empty(&fhc->queue)) {
+ list_move(fhc->queue.next, &fhc->active_list);
+ fhc_dostart(fhc, fhc_first_active(fhc));
+ }
+ spin_unlock_irqrestore(&fhc->lock, flags);
+}
+
+static inline void fhc_dump_lli(struct fh_dma_chan *fhc, struct fh_lli *lli)
+{
+ dev_crit(chan2dev(&fhc->chan), " desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
+ lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo);
+
+}
+
+static void fhc_handle_error(struct fh_dma *fhd, struct fh_dma_chan *fhc)
+{
+ struct fh_desc *bad_desc;
+ struct fh_desc *child;
+ unsigned long flags;
+
+ fhc_scan_descriptors(fhd, fhc);
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ /*
+ * The descriptor currently at the head of the active list is
+ * borked. Since we don't have any way to report errors, we'll
+ * just have to scream loudly and try to carry on.
+ */
+ bad_desc = fhc_first_active(fhc);
+ list_del_init(&bad_desc->desc_node);
+ list_move(fhc->queue.next, fhc->active_list.prev);
+
+ /* Clear the error flag and try to restart the controller */
+ dma_writel(fhd, CLEAR.ERROR, fhc->mask);
+ if (!list_empty(&fhc->active_list))
+ fhc_dostart(fhc, fhc_first_active(fhc));
+
+ /*
+ * WARN may seem harsh, but since this only happens
+ * when someone submits a bad physical address in a
+ * descriptor, we should consider ourselves lucky that the
+ * controller flagged an error instead of scribbling over
+ * random memory locations.
+ */
+ dev_WARN(chan2dev(&fhc->chan), "Bad descriptor submitted for DMA!\n"
+ " cookie: %d\n", bad_desc->txd.cookie);
+ fhc_dump_lli(fhc, &bad_desc->lli);
+ list_for_each_entry(child, &bad_desc->tx_list, desc_node)
+ fhc_dump_lli(fhc, &child->lli);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ /* Pretend the descriptor completed successfully */
+ fhc_descriptor_complete(fhc, bad_desc, true);
+}
+
+/* --------------------- Cyclic DMA API extensions -------------------- */
+
+inline dma_addr_t fh_dma_get_src_addr(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+
+ return channel_readl(fhc, SAR);
+}
+EXPORT_SYMBOL(fh_dma_get_src_addr);
+
+inline dma_addr_t fh_dma_get_dst_addr(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+
+ return channel_readl(fhc, DAR);
+}
+EXPORT_SYMBOL(fh_dma_get_dst_addr);
+
+/* Called with fhc->lock held and all DMAC interrupts disabled */
+static void fhc_handle_cyclic(struct fh_dma *fhd, struct fh_dma_chan *fhc,
+ u32 status_err, u32 status_xfer, u32 status_block)
+{
+ unsigned long flags;
+
+ if (status_block & fhc->mask) {
+ void (*callback) (void *param);
+ void *callback_param;
+
+ dev_vdbg(chan2dev(&fhc->chan), "new cyclic period llp 0x%08x\n",
+ channel_readl(fhc, LLP));
+ dma_writel(fhd, CLEAR.BLOCK, fhc->mask);
+
+ callback = fhc->cdesc->period_callback;
+ callback_param = fhc->cdesc->period_callback_param;
+
+ if (callback)
+ callback(callback_param);
+ }
+
+ /*
+ * Error and transfer complete are highly unlikely, and will most
+ * likely be due to a configuration error by the user.
+ */
+ if (unlikely(status_err & fhc->mask) ||
+ unlikely(status_xfer & fhc->mask)) {
+ int i;
+
+ dev_err(chan2dev(&fhc->chan), "cyclic DMA unexpected %s "
+ "interrupt, stopping DMA transfer\n",
+ status_xfer ? "xfer" : "error");
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ fhc_dump_chan_regs(fhc);
+
+ fhc_chan_disable(fhd, fhc);
+
+ /* Make sure DMA does not restart by loading a new list */
+ channel_writel(fhc, LLP, 0);
+ channel_writel(fhc, CTL_LO, 0);
+ channel_writel(fhc, CTL_HI, 0);
+
+ dma_writel(fhd, CLEAR.ERROR, fhc->mask);
+ dma_writel(fhd, CLEAR.XFER, fhc->mask);
+ dma_writel(fhd, CLEAR.BLOCK, fhc->mask);
+
+ for (i = 0; i < fhc->cdesc->periods; i++)
+ fhc_dump_lli(fhc, &fhc->cdesc->desc[i]->lli);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void fh_dma_tasklet(unsigned long data)
+{
+ struct fh_dma *fhd = (struct fh_dma *)data;
+ struct fh_dma_chan *fhc;
+ u32 status_xfer;
+ u32 status_err;
+ u32 status_block;
+ int i;
+
+ status_xfer = dma_readl(fhd, RAW.XFER);
+ status_block = dma_readl(fhd, RAW.BLOCK);
+ status_err = dma_readl(fhd, RAW.ERROR);
+
+ dev_vdbg(fhd->dma.dev, "%s: status_err=%x\n", __func__, status_err);
+
+ for (i = 0; i < fhd->dma.chancnt; i++) {
+ fhc = &fhd->chan[i];
+ if (test_bit(FH_DMA_IS_CYCLIC, &fhc->flags))
+ fhc_handle_cyclic(fhd, fhc, status_err,
+ status_xfer, status_block);
+ else if (status_err & (1 << i))
+ fhc_handle_error(fhd, fhc);
+ else if (status_xfer & (1 << i))
+ fhc_scan_descriptors(fhd, fhc);
+ }
+
+ /*
+ * Re-enable interrupts.
+ */
+ channel_set_bit(fhd, MASK.XFER, fhd->all_chan_mask);
+ channel_set_bit(fhd, MASK.BLOCK, fhd->all_chan_mask);
+ channel_set_bit(fhd, MASK.ERROR, fhd->all_chan_mask);
+}
+
+static irqreturn_t fh_dma_interrupt(int irq, void *dev_id)
+{
+ struct fh_dma *fhd = dev_id;
+ u32 status;
+
+ dev_vdbg(fhd->dma.dev, "%s: status=0x%x\n", __func__,
+ dma_readl(fhd, STATUS_INT));
+
+ /*
+ * Just disable the interrupts. We'll turn them back on in the
+ * softirq handler.
+ */
+ channel_clear_bit(fhd, MASK.XFER, fhd->all_chan_mask);
+ channel_clear_bit(fhd, MASK.BLOCK, fhd->all_chan_mask);
+ channel_clear_bit(fhd, MASK.ERROR, fhd->all_chan_mask);
+
+ status = dma_readl(fhd, STATUS_INT);
+ if (status) {
+ dev_err(fhd->dma.dev,
+ "BUG: Unexpected interrupts pending: 0x%x\n",
+ status);
+
+ /* Try to recover */
+ channel_clear_bit(fhd, MASK.XFER, (1 << 8) - 1);
+ channel_clear_bit(fhd, MASK.BLOCK, (1 << 8) - 1);
+ channel_clear_bit(fhd, MASK.SRC_TRAN, (1 << 8) - 1);
+ channel_clear_bit(fhd, MASK.DST_TRAN, (1 << 8) - 1);
+ channel_clear_bit(fhd, MASK.ERROR, (1 << 8) - 1);
+ }
+
+ tasklet_schedule(&fhd->tasklet);
+
+ return IRQ_HANDLED;
+}
+
+/*----------------------------------------------------------------------*/
+
+static dma_cookie_t fhc_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct fh_desc *desc = txd_to_fh_desc(tx);
+ struct fh_dma_chan *fhc = to_fh_dma_chan(tx->chan);
+ dma_cookie_t cookie;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ cookie = dma_cookie_assign(tx);
+
+ /*
+ * REVISIT: We should attempt to chain as many descriptors as
+ * possible, perhaps even appending to those already submitted
+ * for DMA. But this is hard to do in a race-free manner.
+ */
+ if (list_empty(&fhc->active_list)) {
+ dev_vdbg(chan2dev(tx->chan), "%s: started %u\n", __func__,
+ desc->txd.cookie);
+ list_add_tail(&desc->desc_node, &fhc->active_list);
+ fhc_dostart(fhc, fhc_first_active(fhc));
+ } else {
+ dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__,
+ desc->txd.cookie);
+
+ list_add_tail(&desc->desc_node, &fhc->queue);
+ }
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ return cookie;
+}
+
+static struct dma_async_tx_descriptor *
+fhc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma *fhd = to_fh_dma(chan->device);
+ struct fh_desc *desc;
+ struct fh_desc *first;
+ struct fh_desc *prev;
+ size_t xfer_count;
+ size_t offset;
+ unsigned int src_width;
+ unsigned int dst_width;
+ unsigned int data_width;
+ u32 ctllo;
+
+ dev_vdbg(chan2dev(chan),
+ "%s: d0x%llx s0x%llx l0x%zx f0x%lx\n", __func__,
+ (unsigned long long)dest, (unsigned long long)src,
+ len, flags);
+
+ if (unlikely(!len)) {
+ dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__);
+ return NULL;
+ }
+
+ fhc->direction = DMA_MEM_TO_MEM;
+
+ data_width = min_t(unsigned int, fhd->data_width[fhc->src_master],
+ fhd->data_width[fhc->dst_master]);
+
+ src_width = dst_width = min_t(unsigned int, data_width,
+ fhc_fast_fls(src | dest | len));
+
+ ctllo = FHC_DEFAULT_CTLLO(chan)
+ | FHC_CTLL_DST_WIDTH(dst_width)
+ | FHC_CTLL_SRC_WIDTH(src_width)
+ | FHC_CTLL_DST_INC
+ | FHC_CTLL_SRC_INC
+ | FHC_CTLL_FC_M2M;
+ prev = first = NULL;
+
+ for (offset = 0; offset < len; offset += xfer_count << src_width) {
+ xfer_count = min_t(size_t, (len - offset) >> src_width,
+ fhc->block_size);
+
+ desc = fhc_desc_get(fhc);
+ if (!desc)
+ goto err_desc_get;
+
+ desc->lli.sar = src + offset;
+ desc->lli.dar = dest + offset;
+ desc->lli.ctllo = ctllo;
+ desc->lli.ctlhi = xfer_count;
+ desc->len = xfer_count << src_width;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ list_add_tail(&desc->desc_node,
+ &first->tx_list);
+ }
+ prev = desc;
+ }
+
+ if (flags & DMA_PREP_INTERRUPT)
+ /* Trigger interrupt after last block */
+ prev->lli.ctllo |= FHC_CTLL_INT_EN;
+
+ prev->lli.llp = 0;
+ first->txd.flags = flags;
+ first->total_len = len;
+
+ return &first->txd;
+
+err_desc_get:
+ fhc_desc_put(fhc, first);
+ return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+fhc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ /*struct fh_dma *fhd = to_fh_dma(chan->device);*/
+ struct dma_slave_config *sconfig = &fhc->dma_sconfig;
+ struct fh_desc *prev;
+ struct fh_desc *first;
+ u32 ctllo;
+ dma_addr_t reg;
+ unsigned int reg_width;
+ unsigned int mem_width;
+ unsigned int data_width;
+ unsigned int i;
+ struct scatterlist *sg;
+ size_t total_len = 0;
+ struct fh_dma_extra *ext_para = (struct fh_dma_extra *)context;
+ dev_vdbg(chan2dev(chan), "%s\n", __func__);
+
+ if (unlikely(!is_slave_direction(direction) || !sg_len))
+ return NULL;
+
+ fhc->direction = direction;
+
+ prev = first = NULL;
+ if (ext_para)
+ memcpy(&fhc->ext_para, ext_para, sizeof(struct fh_dma_extra));
+
+ switch (direction) {
+ case DMA_MEM_TO_DEV:
+ reg_width = __fls(sconfig->dst_addr_width);
+ reg = sconfig->dst_addr;
+ if(!ext_para){
+ ctllo = (FHC_DEFAULT_CTLLO(chan)
+ | FHC_CTLL_DST_WIDTH(reg_width)
+ | FHC_CTLL_DST_FIX
+ | FHC_CTLL_SRC_INC);
+ }
+ else{
+ ctllo = (FHC_DEFAULT_CTLLO(chan) | FHC_CTLL_DST_WIDTH(reg_width));
+ ctllo |= ext_para->sinc << 9;
+ ctllo |= ext_para->dinc << 7;
+ ctllo &= ~(FHC_CTLL_SMS(3));
+ ctllo &= ~(FHC_CTLL_DMS(3));
+ ctllo |= FHC_CTLL_SMS(ext_para->src_master);
+ ctllo |= FHC_CTLL_DMS(ext_para->dst_master);
+ }
+
+ ctllo |= sconfig->device_fc ? FHC_CTLL_FC(FH_DMA_FC_P_M2P) :
+ FHC_CTLL_FC(FH_DMA_FC_D_M2P);
+
+ /*data_width = fhd->data_width[fhc->src_master];*/
+ data_width = __fls(sconfig->src_addr_width);
+ for_each_sg(sgl, sg, sg_len, i) {
+ struct fh_desc *desc;
+ u32 len, dlen, mem;
+
+ mem = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+
+ mem_width = min_t(unsigned int,
+ data_width, fhc_fast_fls(mem | len));
+
+slave_sg_todev_fill_desc:
+ desc = fhc_desc_get(fhc);
+ if (!desc) {
+ dev_err(chan2dev(chan),
+ "not enough descriptors available\n");
+ goto err_desc_get;
+ }
+
+ desc->lli.sar = mem;
+ desc->lli.dar = reg;
+ desc->lli.ctllo = ctllo | FHC_CTLL_SRC_WIDTH(mem_width);
+ if ((len >> mem_width) > fhc->block_size) {
+ dlen = fhc->block_size << mem_width;
+ mem += dlen;
+ len -= dlen;
+ } else {
+ dlen = len;
+ len = 0;
+ }
+
+ desc->lli.ctlhi = dlen >> mem_width;
+ desc->len = dlen;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ list_add_tail(&desc->desc_node,
+ &first->tx_list);
+ }
+ prev = desc;
+ total_len += dlen;
+
+ if (len)
+ goto slave_sg_todev_fill_desc;
+ }
+ break;
+ case DMA_DEV_TO_MEM:
+ reg_width = __fls(sconfig->src_addr_width);
+ reg = sconfig->src_addr;
+
+ if(!ext_para){
+ ctllo = (FHC_DEFAULT_CTLLO(chan)
+ | FHC_CTLL_SRC_WIDTH(reg_width)
+ | FHC_CTLL_DST_INC
+ | FHC_CTLL_SRC_FIX);
+ }
+ else{
+ ctllo = (FHC_DEFAULT_CTLLO(chan) | FHC_CTLL_SRC_WIDTH(reg_width));
+ ctllo |= ext_para->sinc << 9;
+ ctllo |= ext_para->dinc << 7;
+ ctllo &= ~(FHC_CTLL_SMS(3));
+ ctllo &= ~(FHC_CTLL_DMS(3));
+ ctllo |= FHC_CTLL_SMS(ext_para->src_master);
+ ctllo |= FHC_CTLL_DMS(ext_para->dst_master);
+ }
+
+
+ ctllo |= sconfig->device_fc ? FHC_CTLL_FC(FH_DMA_FC_P_P2M) :
+ FHC_CTLL_FC(FH_DMA_FC_D_P2M);
+
+ /*data_width = fhd->data_width[fhc->dst_master];*/
+ data_width = __fls(sconfig->dst_addr_width);
+ for_each_sg(sgl, sg, sg_len, i) {
+ struct fh_desc *desc;
+ u32 len, dlen, mem;
+
+ mem = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+
+ mem_width = min_t(unsigned int,
+ data_width, fhc_fast_fls(mem | len));
+
+slave_sg_fromdev_fill_desc:
+ desc = fhc_desc_get(fhc);
+ if (!desc) {
+ dev_err(chan2dev(chan),
+ "not enough descriptors available\n");
+ goto err_desc_get;
+ }
+
+ desc->lli.sar = reg;
+ desc->lli.dar = mem;
+ desc->lli.ctllo = ctllo | FHC_CTLL_DST_WIDTH(mem_width);
+ if ((len >> reg_width) > fhc->block_size) {
+ dlen = fhc->block_size << reg_width;
+ mem += dlen;
+ len -= dlen;
+ } else {
+ dlen = len;
+ len = 0;
+ }
+ desc->lli.ctlhi = dlen >> reg_width;
+ desc->len = dlen;
+
+ if (!first) {
+ first = desc;
+ } else {
+ prev->lli.llp = desc->txd.phys;
+ list_add_tail(&desc->desc_node,
+ &first->tx_list);
+ }
+ prev = desc;
+ total_len += dlen;
+
+ if (len)
+ goto slave_sg_fromdev_fill_desc;
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ if (flags & DMA_PREP_INTERRUPT)
+ /* Trigger interrupt after last block */
+ prev->lli.ctllo |= FHC_CTLL_INT_EN;
+
+ prev->lli.llp = 0;
+ first->total_len = total_len;
+
+ return &first->txd;
+
+err_desc_get:
+ fhc_desc_put(fhc, first);
+ return NULL;
+}
+
+/*
+ * Fix sconfig's burst size according to fh_dmac. We need to convert them as:
+ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
+ *
+ * NOTE: burst size 2 is not supported by controller.
+ *
+ * This can be done by finding least significant bit set: n & (n - 1)
+ */
+static inline void convert_burst(u32 *maxburst)
+{
+ if (*maxburst > 1)
+ *maxburst = fls(*maxburst) - 2;
+ else
+ *maxburst = 0;
+}
+
+static int
+set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+
+ /* Check if chan will be configured for slave transfers */
+ if (!is_slave_direction(sconfig->direction))
+ return -EINVAL;
+
+ memcpy(&fhc->dma_sconfig, sconfig, sizeof(*sconfig));
+ fhc->direction = sconfig->direction;
+
+ /* Take the request line from slave_id member */
+ if (fhc->request_line == ~0)
+ fhc->request_line = sconfig->slave_id;
+
+ convert_burst(&fhc->dma_sconfig.src_maxburst);
+ convert_burst(&fhc->dma_sconfig.dst_maxburst);
+
+ return 0;
+}
+
+static inline void fhc_chan_pause(struct fh_dma_chan *fhc)
+{
+ u32 cfglo = channel_readl(fhc, CFG_LO);
+ unsigned int count = 20; /* timeout iterations */
+
+ channel_writel(fhc, CFG_LO, cfglo | FHC_CFGL_CH_SUSP);
+ while (!(channel_readl(fhc, CFG_LO) & FHC_CFGL_FIFO_EMPTY) && count--)
+ udelay(2);
+
+ fhc->paused = true;
+}
+
+static inline void fhc_chan_resume(struct fh_dma_chan *fhc)
+{
+ u32 cfglo = channel_readl(fhc, CFG_LO);
+
+ channel_writel(fhc, CFG_LO, cfglo & ~FHC_CFGL_CH_SUSP);
+
+ fhc->paused = false;
+}
+
+static int fhc_device_config(struct dma_chan *chan, struct dma_slave_config *config)
+{
+ return set_runtime_config(chan, config);
+}
+
+static int fhc_device_pause(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ fhc_chan_pause(fhc);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ return 0;
+}
+
+static int fhc_device_resume(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ unsigned long flags;
+
+ if (!fhc->paused)
+ return 0;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ fhc_chan_resume(fhc);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ return 0;
+}
+
+static int fhc_device_terminate_all(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma *fhd = to_fh_dma(chan->device);
+ struct fh_desc *desc, *_desc;
+ unsigned long flags;
+ LIST_HEAD(list);
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ clear_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags);
+
+ fhc_chan_disable(fhd, fhc);
+
+ fhc_chan_resume(fhc);
+
+ /* active_list entries will end up before queued entries */
+ list_splice_init(&fhc->queue, &list);
+ list_splice_init(&fhc->active_list, &list);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ /* Flush all pending and queued descriptors */
+ list_for_each_entry_safe(desc, _desc, &list, desc_node)
+ fhc_descriptor_complete(fhc, desc, false);
+
+ return 0;
+}
+
+static inline u32 fhc_get_residue(struct fh_dma_chan *fhc)
+{
+ unsigned long flags;
+ u32 residue;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ residue = fhc->residue;
+ if (test_bit(FH_DMA_IS_SOFT_LLP, &fhc->flags) && residue)
+ residue -= fhc_get_sent(fhc);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return residue;
+}
+
+static enum dma_status
+fhc_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ struct dma_tx_state *txstate)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ enum dma_status ret;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret != DMA_COMPLETE) {
+ fhc_scan_descriptors(to_fh_dma(chan->device), fhc);
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ }
+
+ if (ret != DMA_COMPLETE)
+ dma_set_residue(txstate, fhc_get_residue(fhc));
+
+ if (fhc->paused)
+ return DMA_PAUSED;
+
+ return ret;
+}
+
+static void fhc_issue_pending(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+
+ if (!list_empty(&fhc->queue))
+ fhc_scan_descriptors(to_fh_dma(chan->device), fhc);
+}
+
+static int fhc_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma *fhd = to_fh_dma(chan->device);
+ struct fh_desc *desc;
+ int i;
+ unsigned long flags;
+#ifdef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+ int j;
+ dma_addr_t phys;
+#endif
+ dev_vdbg(chan2dev(chan), "%s\n", __func__);
+
+ /* ASSERT: channel is idle */
+ if (dma_readl(fhd, CH_EN) & fhc->mask) {
+ dev_dbg(chan2dev(chan), "DMA channel not idle?\n");
+ return -EIO;
+ }
+
+ dma_cookie_init(chan);
+
+ /*
+ * NOTE: some controllers may have additional features that we
+ * need to initialize here, like "scatter-gather" (which
+ * doesn't mean what you think it means), and status writeback.
+ */
+
+ fhc_set_masters(fhc);
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ i = fhc->descs_allocated;
+#ifdef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+ desc = (struct fh_desc *)dma_alloc_coherent(fhd->dma.dev,
+ sizeof(struct fh_desc) * NR_DESCS_PER_CHANNEL, &phys, GFP_KERNEL);
+ if (!desc)
+ goto err_desc_alloc;
+ fhc->dma_vaddr = (void *)desc;
+ fhc->dma_paddr = phys;
+ memset(desc, 0, sizeof(struct fh_desc) * NR_DESCS_PER_CHANNEL);
+ for (j = 0; j < NR_DESCS_PER_CHANNEL; j++, desc++)
+ {
+ INIT_LIST_HEAD(&desc->tx_list);
+ dma_async_tx_descriptor_init(&desc->txd, chan);
+ desc->txd.tx_submit = fhc_tx_submit;
+ desc->txd.flags = DMA_CTRL_ACK;
+ desc->txd.phys = phys + (j * sizeof(struct fh_desc));
+ fhc_desc_put(fhc, desc);
+ i = ++fhc->descs_allocated;
+ }
+#else
+ while (fhc->descs_allocated < NR_DESCS_PER_CHANNEL) {
+ dma_addr_t phys;
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ desc = dma_pool_alloc(fhd->desc_pool, GFP_ATOMIC, &phys);
+ if (!desc)
+ goto err_desc_alloc;
+
+ memset(desc, 0, sizeof(struct fh_desc));
+
+ INIT_LIST_HEAD(&desc->tx_list);
+ dma_async_tx_descriptor_init(&desc->txd, chan);
+ desc->txd.tx_submit = fhc_tx_submit;
+ desc->txd.flags = DMA_CTRL_ACK;
+ desc->txd.phys = phys;
+
+ fhc_desc_put(fhc, desc);
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ i = ++fhc->descs_allocated;
+ }
+#endif
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ return i;
+
+err_desc_alloc:
+ dev_err(chan2dev(chan), "only allocated %d descriptors\n", i);
+
+ return i;
+}
+
+static void fhc_free_chan_resources(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma *fhd = to_fh_dma(chan->device);
+#ifndef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+ struct fh_desc *desc, *_desc;
+#endif
+ unsigned long flags;
+ LIST_HEAD(list);
+
+ dev_dbg(chan2dev(chan), "%s: descs allocated=%u\n", __func__,
+ fhc->descs_allocated);
+
+ /* ASSERT: channel is idle */
+ BUG_ON(!list_empty(&fhc->active_list));
+ BUG_ON(!list_empty(&fhc->queue));
+ BUG_ON(dma_readl(to_fh_dma(chan->device), CH_EN) & fhc->mask);
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ list_splice_init(&fhc->free_list, &list);
+ fhc->descs_allocated = 0;
+ fhc->initialized = false;
+ fhc->request_line = ~0;
+
+ /* Disable interrupts */
+ channel_clear_bit(fhd, MASK.XFER, fhc->mask);
+ channel_clear_bit(fhd, MASK.BLOCK, fhc->mask);
+ channel_clear_bit(fhd, MASK.ERROR, fhc->mask);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+#ifdef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+ dma_free_coherent(fhd->dma.dev,
+ sizeof(struct fh_desc) * NR_DESCS_PER_CHANNEL,
+ fhc->dma_vaddr, fhc->dma_paddr);
+#else
+
+ list_for_each_entry_safe(desc, _desc, &list, desc_node) {
+ dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc);
+ dma_pool_free(fhd->desc_pool, desc, desc->txd.phys);
+ }
+#endif
+
+
+ dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
+}
+
+
+/* --------------------- Cyclic DMA API extensions -------------------- */
+
+/**
+ * fh_dma_cyclic_start - start the cyclic DMA transfer
+ * @chan: the DMA channel to start
+ *
+ * Must be called with soft interrupts disabled. Returns zero on success or
+ * -errno on failure.
+ */
+int fh_dma_cyclic_start(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma *fhd = to_fh_dma(fhc->chan.device);
+ unsigned long flags;
+
+ if (!test_bit(FH_DMA_IS_CYCLIC, &fhc->flags)) {
+ dev_err(chan2dev(&fhc->chan), "missing prep for cyclic DMA\n");
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ /* Assert channel is idle */
+ if (dma_readl(fhd, CH_EN) & fhc->mask) {
+ dev_err(chan2dev(&fhc->chan),
+ "BUG: Attempted to start non-idle channel\n");
+ fhc_dump_chan_regs(fhc);
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ return -EBUSY;
+ }
+
+ dma_writel(fhd, CLEAR.ERROR, fhc->mask);
+ dma_writel(fhd, CLEAR.XFER, fhc->mask);
+ dma_writel(fhd, CLEAR.BLOCK, fhc->mask);
+
+ fhc_initialize(fhc);
+
+ /* Setup DMAC channel registers */
+ channel_writel(fhc, LLP, fhc->cdesc->desc[0]->txd.phys);
+ channel_writel(fhc, CTL_LO, FHC_CTLL_LLP_D_EN | FHC_CTLL_LLP_S_EN);
+ channel_writel(fhc, CTL_HI, 0);
+
+ channel_set_bit(fhd, CH_EN, fhc->mask);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(fh_dma_cyclic_start);
+
+/**
+ * fh_dma_cyclic_stop - stop the cyclic DMA transfer
+ * @chan: the DMA channel to stop
+ *
+ * Must be called with soft interrupts disabled.
+ */
+void fh_dma_cyclic_stop(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma *fhd = to_fh_dma(fhc->chan.device);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ fhc_chan_disable(fhd, fhc);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+}
+EXPORT_SYMBOL(fh_dma_cyclic_stop);
+
+/**
+ * fh_dma_cyclic_prep - prepare the cyclic DMA transfer
+ * @chan: the DMA channel to prepare
+ * @buf_addr: physical DMA address where the buffer starts
+ * @buf_len: total number of bytes for the entire buffer
+ * @period_len: number of bytes for each period
+ * @direction: transfer direction, to or from device
+ *
+ * Must be called before trying to start the transfer. Returns a valid struct
+ * fh_cyclic_desc if successful or an ERR_PTR(-errno) if not successful.
+ */
+struct fh_cyclic_desc *fh_dma_cyclic_prep(struct dma_chan *chan,
+ dma_addr_t buf_addr, size_t buf_len, size_t period_len,
+ enum dma_transfer_direction direction)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma_slave *fhs = chan->private;
+ struct fh_cyclic_desc *cdesc;
+ struct fh_cyclic_desc *retval = NULL;
+ struct fh_desc *desc;
+ struct fh_desc *last = NULL;
+ unsigned long was_cyclic;
+ unsigned int reg_width;
+ unsigned int periods;
+ unsigned int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+ if (fhc->nollp) {
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ dev_dbg(chan2dev(&fhc->chan),
+ "channel doesn't support LLP transfers\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!list_empty(&fhc->queue) || !list_empty(&fhc->active_list)) {
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ dev_dbg(chan2dev(&fhc->chan),
+ "queue and/or active list are not empty\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ was_cyclic = test_and_set_bit(FH_DMA_IS_CYCLIC, &fhc->flags);
+ spin_unlock_irqrestore(&fhc->lock, flags);
+ if (was_cyclic) {
+ dev_dbg(chan2dev(&fhc->chan),
+ "channel already prepared for cyclic DMA\n");
+ return ERR_PTR(-EBUSY);
+ }
+
+ retval = ERR_PTR(-EINVAL);
+
+ reg_width = fhs->reg_width;
+
+ if (unlikely(!is_slave_direction(direction)))
+ goto out_err;
+
+ fhc->direction = direction;
+
+ periods = buf_len / period_len;
+
+ /* Check for too big/unaligned periods and unaligned DMA buffer. */
+ if (period_len > (fhc->block_size << reg_width))
+ goto out_err;
+ if (unlikely(period_len & ((1 << reg_width) - 1)))
+ goto out_err;
+ if (unlikely(buf_addr & ((1 << reg_width) - 1)))
+ goto out_err;
+
+ retval = ERR_PTR(-ENOMEM);
+
+ if (periods > NR_DESCS_PER_CHANNEL)
+ goto out_err;
+
+ cdesc = kzalloc(sizeof(struct fh_cyclic_desc), GFP_KERNEL);
+ if (!cdesc)
+ goto out_err;
+
+ cdesc->desc = kzalloc(sizeof(struct fh_desc *) * periods, GFP_KERNEL);
+ if (!cdesc->desc)
+ goto out_err_alloc;
+
+ for (i = 0; i < periods; i++) {
+ desc = fhc_desc_get(fhc);
+ if (!desc)
+ goto out_err_desc_get;
+
+ switch (direction) {
+ case DMA_MEM_TO_DEV:
+ desc->lli.dar = fhs->tx_reg;
+ desc->lli.sar = buf_addr + (period_len * i);
+ desc->lli.ctllo = (FHC_DEFAULT_CTLLO_OLD(chan->private)
+ | FHC_CTLL_DST_WIDTH(reg_width)
+ | FHC_CTLL_SRC_WIDTH(reg_width)
+ | FHC_CTLL_DST_FIX
+ | FHC_CTLL_SRC_INC
+ | FHC_CTLL_FC(fhs->fc)
+ | FHC_CTLL_INT_EN);
+
+ break;
+ case DMA_DEV_TO_MEM:
+ desc->lli.dar = buf_addr + (period_len * i);
+ desc->lli.sar = fhs->rx_reg;
+ desc->lli.ctllo = (FHC_DEFAULT_CTLLO_OLD(chan->private)
+ | FHC_CTLL_SRC_WIDTH(reg_width)
+ | FHC_CTLL_DST_WIDTH(reg_width)
+ | FHC_CTLL_DST_INC
+ | FHC_CTLL_SRC_FIX
+ | FHC_CTLL_FC(fhs->fc)
+ | FHC_CTLL_INT_EN);
+
+
+ break;
+ default:
+ break;
+ }
+
+ desc->lli.ctlhi = (period_len >> reg_width);
+ cdesc->desc[i] = desc;
+
+ if (last)
+ {
+ last->lli.llp = desc->txd.phys;
+ dma_sync_single_for_device(chan2parent(chan),
+ last->txd.phys,
+ sizeof(last->lli),
+ DMA_TO_DEVICE);
+ }
+
+ last = desc;
+ }
+
+ /* Let's make a cyclic list */
+ last->lli.llp = cdesc->desc[0]->txd.phys;
+ dma_sync_single_for_device(chan2parent(chan), last->txd.phys,
+ sizeof(last->lli), DMA_TO_DEVICE);
+
+ dev_dbg(chan2dev(&fhc->chan), "cyclic prepared buf 0x%llx len %zu "
+ "period %zu periods %d\n", (unsigned long long)buf_addr,
+ buf_len, period_len, periods);
+
+ cdesc->periods = periods;
+ fhc->cdesc = cdesc;
+
+ return cdesc;
+
+out_err_desc_get:
+ while (i--)
+ fhc_desc_put(fhc, cdesc->desc[i]);
+out_err_alloc:
+ kfree(cdesc);
+out_err:
+ clear_bit(FH_DMA_IS_CYCLIC, &fhc->flags);
+ return (struct fh_cyclic_desc *)retval;
+}
+EXPORT_SYMBOL(fh_dma_cyclic_prep);
+
+/**
+ * fh_dma_cyclic_free - free a prepared cyclic DMA transfer
+ * @chan: the DMA channel to free
+ */
+void fh_dma_cyclic_free(struct dma_chan *chan)
+{
+ struct fh_dma_chan *fhc = to_fh_dma_chan(chan);
+ struct fh_dma *fhd = to_fh_dma(fhc->chan.device);
+ struct fh_cyclic_desc *cdesc = fhc->cdesc;
+ int i;
+ unsigned long flags;
+
+ dev_dbg(chan2dev(&fhc->chan), "%s\n", __func__);
+
+ if (!cdesc)
+ return;
+
+ spin_lock_irqsave(&fhc->lock, flags);
+
+ fhc_chan_disable(fhd, fhc);
+
+ dma_writel(fhd, CLEAR.ERROR, fhc->mask);
+ dma_writel(fhd, CLEAR.XFER, fhc->mask);
+ dma_writel(fhd, CLEAR.BLOCK, fhc->mask);
+
+ spin_unlock_irqrestore(&fhc->lock, flags);
+
+ for (i = 0; i < cdesc->periods; i++)
+ fhc_desc_put(fhc, cdesc->desc[i]);
+
+ kfree(cdesc->desc);
+ kfree(cdesc);
+
+ clear_bit(FH_DMA_IS_CYCLIC, &fhc->flags);
+}
+EXPORT_SYMBOL(fh_dma_cyclic_free);
+
+/*----------------------------------------------------------------------*/
+
+static void fh_dma_off(struct fh_dma *fhd)
+{
+ int i;
+
+ dma_writel(fhd, CFG, 0);
+
+ channel_clear_bit(fhd, MASK.XFER, fhd->all_chan_mask);
+ channel_clear_bit(fhd, MASK.BLOCK, fhd->all_chan_mask);
+ channel_clear_bit(fhd, MASK.SRC_TRAN, fhd->all_chan_mask);
+ channel_clear_bit(fhd, MASK.DST_TRAN, fhd->all_chan_mask);
+ channel_clear_bit(fhd, MASK.ERROR, fhd->all_chan_mask);
+
+ while (dma_readl(fhd, CFG) & FH_CFG_DMA_EN)
+ cpu_relax();
+
+ for (i = 0; i < fhd->dma.chancnt; i++)
+ fhd->chan[i].initialized = false;
+}
+
+static int fh_dma_probe(struct platform_device *pdev)
+{
+ struct fh_dma_platform_data *pdata;
+ struct device_node *np = pdev->dev.of_node;
+ struct fh_dma *fhd;
+ size_t size;
+ void __iomem *regs;
+ bool autocfg;
+ unsigned int fh_params;
+ unsigned int nr_channels;
+ unsigned int max_blk_size = 0;
+ int irq;
+ int err;
+ int i;
+ struct resource *res;
+
+ if (np && !IS_ERR(np)) {
+ regs = of_iomap(np, 0);
+ if (!regs) {
+ err = -ENOMEM;
+ goto err_release_r;
+ }
+ irq = irq_of_parse_and_map(np, 0);
+ } else {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ goto err_release_r;
+ }
+ regs = ioremap(res->start, resource_size(res));
+ if (regs == NULL) {
+ dev_err(&pdev->dev, "ioremap resource error\n");
+ goto err_release_r;
+ }
+ irq = platform_get_irq(pdev, 0);
+ irq = irq_create_mapping(NULL, irq);
+ }
+
+ /* Apply default dma_mask if needed */
+ if (!pdev->dev.dma_mask) {
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ }
+
+ fh_params = dma_read_byaddr(regs, FH_PARAMS);
+ autocfg = fh_params >> FH_PARAMS_EN & 0x1;
+ dev_dbg(&pdev->dev, "FH_PARAMS: 0x%08x\n", fh_params);
+ pdata = dev_get_platdata(&pdev->dev);
+ if (!pdata && autocfg) {
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ /* Fill platform data with the default values */
+ pdata->is_private = true;
+ pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING;
+ pdata->chan_priority = CHAN_PRIORITY_ASCENDING;
+ } else if (!pdata || pdata->nr_channels > FH_DMA_MAX_NR_CHANNELS)
+ return -EINVAL;
+
+ if (autocfg)
+ nr_channels = (fh_params >> FH_PARAMS_NR_CHAN & 0x7) + 1;
+ else
+ nr_channels = pdata->nr_channels;
+
+ size = sizeof(struct fh_dma) + nr_channels * sizeof(struct fh_dma_chan);
+ fhd = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ fhd->regs = regs;
+ if (!fhd)
+ return -ENOMEM;
+
+ if (np && !IS_ERR(np))
+ fhd->clk = of_clk_get(np, 0);
+ else
+ fhd->clk = clk_get(&pdev->dev, pdata->clk_name);
+ if (IS_ERR(fhd->clk)) {
+ devm_kfree(&pdev->dev, fhd);
+ return EINVAL;
+ }
+ clk_prepare_enable(fhd->clk);
+ /* Get hardware configuration parameters */
+ if (autocfg) {
+ max_blk_size = dma_readl(fhd, MAX_BLK_SIZE);
+
+ fhd->nr_masters = (fh_params >> FH_PARAMS_NR_MASTER & 3) + 1;
+ for (i = 0; i < fhd->nr_masters; i++) {
+ fhd->data_width[i] =
+ (fh_params >> FH_PARAMS_DATA_WIDTH(i) & 3) + 2;
+ }
+ } else {
+ fhd->nr_masters = pdata->nr_masters;
+ memcpy(fhd->data_width, pdata->data_width, 4);
+ }
+
+ /* Calculate all channel mask before DMA setup */
+ fhd->all_chan_mask = (1 << nr_channels) - 1;
+
+ /* Force dma off, just in case */
+ fh_dma_off(fhd);
+
+ /* Disable BLOCK interrupts as well */
+ channel_clear_bit(fhd, MASK.BLOCK, fhd->all_chan_mask);
+
+ err = devm_request_irq(&pdev->dev, irq, fh_dma_interrupt, 0,
+ "fh-dmac", fhd);
+
+ if (err)
+ return err;
+
+ platform_set_drvdata(pdev, fhd);
+#ifndef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+ /* Create a pool of consistent memory blocks for hardware descriptors */
+ fhd->desc_pool = dmam_pool_create("fh_dmac_desc_pool", &pdev->dev,
+ sizeof(struct fh_desc), 4, 0);
+ if (!fhd->desc_pool) {
+ dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
+ return -ENOMEM;
+ }
+#endif
+ tasklet_init(&fhd->tasklet, fh_dma_tasklet, (unsigned long)fhd);
+
+ INIT_LIST_HEAD(&fhd->dma.channels);
+ for (i = 0; i < nr_channels; i++) {
+ struct fh_dma_chan *fhc = &fhd->chan[i];
+ int r = nr_channels - i - 1;
+
+ fhc->chan.device = &fhd->dma;
+ dma_cookie_init(&fhc->chan);
+ if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
+ list_add_tail(&fhc->chan.device_node,
+ &fhd->dma.channels);
+ else
+ list_add(&fhc->chan.device_node, &fhd->dma.channels);
+
+ /* 7 is highest priority & 0 is lowest. */
+ if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
+ fhc->priority = r;
+ else
+ fhc->priority = i;
+
+ fhc->ch_regs = &__fh_regs(fhd)->CHAN[i];
+ spin_lock_init(&fhc->lock);
+ fhc->mask = 1 << i;
+
+ INIT_LIST_HEAD(&fhc->active_list);
+ INIT_LIST_HEAD(&fhc->queue);
+ INIT_LIST_HEAD(&fhc->free_list);
+
+ channel_clear_bit(fhd, CH_EN, fhc->mask);
+
+ fhc->direction = DMA_TRANS_NONE;
+ fhc->request_line = ~0;
+
+ /* Hardware configuration */
+ if (autocfg) {
+ unsigned int fhc_params;
+
+ fhc_params = dma_read_byaddr(regs + r * sizeof(u32),
+ FHC_PARAMS);
+
+ dev_dbg(&pdev->dev, "FHC_PARAMS[%d]: 0x%08x\n", i,
+ fhc_params);
+
+ /* Decode maximum block size for given channel. The
+ * stored 4 bit value represents blocks from 0x00 for 3
+ * up to 0x0a for 4095. */
+ fhc->block_size =
+ (4 << ((max_blk_size >> 4 * i) & 0xf)) - 1;
+ fhc->nollp =
+ (fhc_params >> FHC_PARAMS_MBLK_EN & 0x1) == 0;
+ } else {
+ fhc->block_size = pdata->block_size;
+
+ /* Check if channel supports multi block transfer */
+ channel_writel(fhc, LLP, 0xfffffffc);
+ fhc->nollp =
+ (channel_readl(fhc, LLP) & 0xfffffffc) == 0;
+ channel_writel(fhc, LLP, 0);
+ }
+ }
+
+ /* Clear all interrupts on all channels. */
+ dma_writel(fhd, CLEAR.XFER, fhd->all_chan_mask);
+ dma_writel(fhd, CLEAR.BLOCK, fhd->all_chan_mask);
+ dma_writel(fhd, CLEAR.SRC_TRAN, fhd->all_chan_mask);
+ dma_writel(fhd, CLEAR.DST_TRAN, fhd->all_chan_mask);
+ dma_writel(fhd, CLEAR.ERROR, fhd->all_chan_mask);
+
+ dma_cap_set(DMA_MEMCPY, fhd->dma.cap_mask);
+ dma_cap_set(DMA_SLAVE, fhd->dma.cap_mask);
+ if (pdata->is_private)
+ dma_cap_set(DMA_PRIVATE, fhd->dma.cap_mask);
+ fhd->dma.dev = &pdev->dev;
+ fhd->dma.device_alloc_chan_resources = fhc_alloc_chan_resources;
+ fhd->dma.device_free_chan_resources = fhc_free_chan_resources;
+
+ fhd->dma.device_prep_dma_memcpy = fhc_prep_dma_memcpy;
+
+ fhd->dma.device_prep_slave_sg = fhc_prep_slave_sg;
+
+ fhd->dma.device_config = fhc_device_config;
+ fhd->dma.device_pause = fhc_device_pause;
+ fhd->dma.device_resume = fhc_device_resume;
+ fhd->dma.device_terminate_all = fhc_device_terminate_all;
+
+ fhd->dma.device_tx_status = fhc_tx_status;
+ fhd->dma.device_issue_pending = fhc_issue_pending;
+
+ dma_writel(fhd, CFG, FH_CFG_DMA_EN);
+
+ err = dma_async_device_register(&fhd->dma);
+
+ if (err)
+ pr_err("dma register failed, ret %d\n", err);
+
+ dev_info(&pdev->dev, "FH DMA Controller, %d channels\n", nr_channels);
+
+ return 0;
+
+err_release_r:
+ return err;
+}
+
+static int fh_dma_remove(struct platform_device *pdev)
+{
+ struct fh_dma *fhd = platform_get_drvdata(pdev);
+ struct fh_dma_chan *fhc, *_fhc;
+
+ fh_dma_off(fhd);
+ dma_async_device_unregister(&fhd->dma);
+
+ tasklet_kill(&fhd->tasklet);
+
+ list_for_each_entry_safe(fhc, _fhc, &fhd->dma.channels,
+ chan.device_node) {
+ list_del(&fhc->chan.device_node);
+ channel_clear_bit(fhd, CH_EN, fhc->mask);
+ }
+
+ return 0;
+}
+
+static void fh_dma_shutdown(struct platform_device *pdev)
+{
+ struct fh_dma *fhd = platform_get_drvdata(pdev);
+
+ fh_dma_off(fhd);
+ clk_disable_unprepare(fhd->clk);
+}
+
+static int fh_dma_suspend_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fh_dma *fhd = platform_get_drvdata(pdev);
+
+ fh_dma_off(fhd);
+ clk_disable_unprepare(fhd->clk);
+
+ return 0;
+}
+
+static int fh_dma_resume_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fh_dma *fhd = platform_get_drvdata(pdev);
+
+ clk_prepare_enable(fhd->clk);
+ dma_writel(fhd, CFG, FH_CFG_DMA_EN);
+
+ return 0;
+}
+
+static const struct of_device_id fh_dma_of_id_table[] = {
+ { .compatible = "fh,fh-dma" },
+ {}
+};
+
+static const struct dev_pm_ops fh_dma_dev_pm_ops = {
+ .suspend_noirq = fh_dma_suspend_noirq,
+ .resume_noirq = fh_dma_resume_noirq,
+ .freeze_noirq = fh_dma_suspend_noirq,
+ .thaw_noirq = fh_dma_resume_noirq,
+ .restore_noirq = fh_dma_resume_noirq,
+ .poweroff_noirq = fh_dma_suspend_noirq,
+};
+
+static struct platform_driver fh_dma_driver = {
+ .probe = fh_dma_probe,
+ .remove = fh_dma_remove,
+ .shutdown = fh_dma_shutdown,
+ .driver = {
+ .name = "fh_dmac",
+ .pm = &fh_dma_dev_pm_ops,
+ .of_match_table = of_match_ptr(fh_dma_of_id_table),
+ },
+};
+
+static int __init fh_dma_init(void)
+{
+ return platform_driver_register(&fh_dma_driver);
+}
+subsys_initcall(fh_dma_init);
+
+static void __exit fh_dma_exit(void)
+{
+ platform_driver_unregister(&fh_dma_driver);
+}
+module_exit(fh_dma_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("fullhan AHB-DMA devive driver");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 12d417a4..7bff612d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -150,6 +150,12 @@ config GPIO_CLPS711X
help
Say yes here to support GPIO on CLPS711X SoCs.
+config GPIO_FH
+ tristate "FH GPIO support"
+ depends on ARCH_FULLHAN
+ help
+ Say yes here to support GPIO functionality of FH.
+
config GPIO_DAVINCI
bool "TI Davinci/Keystone GPIO support"
default y if ARCH_DAVINCI
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index d074c229..4cfe26e4 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -141,3 +141,4 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
obj-$(CONFIG_GPIO_ZX) += gpio-zx.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
+obj-$(CONFIG_GPIO_FH) += fh_gpio.o
\ No newline at end of file
diff --git a/drivers/gpio/fh_gpio.c b/drivers/gpio/fh_gpio.c
new file mode 100644
index 00000000..90fd50b1
--- /dev/null
+++ b/drivers/gpio/fh_gpio.c
@@ -0,0 +1,889 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <asm-generic/gpio.h>
+#include <mach/fh_gpio_plat.h>
+
+/*
+ * GPIO Direction
+ */
+#define GPIO_DIR_INPUT 0
+#define GPIO_DIR_OUTPUT 1
+
+/*
+ * GPIO interrupt type
+ */
+#define GPIO_INT_TYPE_LEVEL 0
+#define GPIO_INT_TYPE_EDGE 1
+
+/*
+ * GPIO interrupt polarity
+ */
+#define GPIO_INT_POL_LOW 0
+#define GPIO_INT_POL_HIGH 1
+
+#define OFFSET_GPIO_SWPORTA_DR (0x0000)
+#define OFFSET_GPIO_SWPORTA_DDR (0x0004)
+#define OFFSET_GPIO_PORTA_CTL (0x0008)
+#define OFFSET_GPIO_SWPORTB_DR (0x000C)
+#define OFFSET_GPIO_SWPORTB_DDR (0x0010)
+#define OFFSET_GPIO_PORTB_CTL (0x0014)
+#define OFFSET_GPIO_INTEN (0x0030)
+#define OFFSET_GPIO_INTMASK (0x0034)
+#define OFFSET_GPIO_INTTYPE_LEVEL (0x0038)
+#define OFFSET_GPIO_INT_POLARITY (0x003C)
+#define OFFSET_GPIO_INTSTATUS (0x0040)
+#define OFFSET_GPIO_RAWINTSTATUS (0x0044)
+#define OFFSET_GPIO_DEBOUNCE (0x0048)
+#define OFFSET_GPIO_PORTA_EOI (0x004C)
+#define OFFSET_GPIO_EXT_PORTA (0x0050)
+#define OFFSET_GPIO_EXT_PORTB (0x0054)
+#define OFFSET_GPIO_INT_BOTH (0x0068)
+
+struct fh_gpio_chip *fh_gpio0, *fh_gpio1, *fh_gpio2, *fh_gpio3;
+
+static inline void FH_GPIO_SetValue(void __iomem *base, int bit, int val)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_SWPORTA_DR);
+ reg = val ? (reg | (1 << bit)) : (reg & ~(1 << bit));
+ writel(reg, base + OFFSET_GPIO_SWPORTA_DR);
+}
+
+static inline int FH_GPIO_GetValue(void __iomem *base, int bit)
+{
+ return (readl(base + OFFSET_GPIO_EXT_PORTA) >> bit) & 0x1;
+}
+
+static inline void FH_GPIO_SetDirection(void __iomem *base, int bit, int dir)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_SWPORTA_DDR);
+ reg = dir ? reg | (1 << bit) : reg & ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_SWPORTA_DDR);
+}
+
+static inline int FH_GPIO_GetDirection(void __iomem *base, int bit)
+{
+ return (readl(base + OFFSET_GPIO_SWPORTA_DDR) >> bit) & 0x1;
+}
+
+static inline void FH_GPIOB_SetValue(void __iomem *base, int bit, int val)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_SWPORTB_DR);
+ reg = val ? (reg | (1 << bit)) : (reg & ~(1 << bit));
+ writel(reg, base + OFFSET_GPIO_SWPORTB_DR);
+}
+
+static inline int FH_GPIOB_GetValue(void __iomem *base, int bit)
+{
+ return (readl(base + OFFSET_GPIO_EXT_PORTB) >> bit) & 0x1;
+}
+
+static inline void FH_GPIOB_SetDirection(void __iomem *base, int bit, int dir)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_SWPORTB_DDR);
+ reg = dir ? reg | (1 << bit) : reg & ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_SWPORTB_DDR);
+}
+
+static inline int FH_GPIOB_GetDirection(void __iomem *base, int bit)
+{
+ return (readl(base + OFFSET_GPIO_SWPORTB_DDR) >> bit) & 0x1;
+}
+
+static inline void FH_GPIO_EnableDebounce(void __iomem *base, int bit, int bool)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_DEBOUNCE);
+ reg = bool ? reg | (1 << bit) : reg & ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_DEBOUNCE);
+}
+
+static inline void FH_GPIO_SetInterruptType(void __iomem *base, int bit,
+ int type)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_INTTYPE_LEVEL);
+ reg = type ? reg | (1 << bit) : reg & ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_INTTYPE_LEVEL);
+}
+
+static inline void FH_GPIO_SetInterruptPolarity(void __iomem *base, int bit,
+ int pol)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_INT_POLARITY);
+ reg = pol ? reg | (1 << bit) : reg & ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_INT_POLARITY);
+}
+
+static inline void FH_GPIO_Set_BothInterrupt_enable(void __iomem *base, int bit)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_INT_BOTH);
+ reg |= (1 << bit);
+ writel(reg, base + OFFSET_GPIO_INT_BOTH);
+}
+
+static inline void FH_GPIO_Set_BothInterrupt_disable(void __iomem *base,
+ int bit)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_INT_BOTH);
+ reg &= ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_INT_BOTH);
+}
+
+static inline void FH_GPIO_EnableInterruptMask(void __iomem *base, int bit,
+ int bool)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_INTMASK);
+ reg = bool ? reg | (1 << bit) : reg & ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_INTMASK);
+}
+
+static inline void FH_GPIO_EnableInterrupt(void __iomem *base, int bit, int bool)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_INTEN);
+ reg = bool ? reg | (1 << bit) : reg & ~(1 << bit);
+ writel(reg, base + OFFSET_GPIO_INTEN);
+}
+
+static inline void FH_GPIO_SetEnableInterrupts(void __iomem *base,
+ unsigned int val)
+{
+ writel(val, base + OFFSET_GPIO_INTEN);
+}
+
+static inline unsigned int FH_GPIO_GetEnableInterrupts(void __iomem *base)
+{
+ return readl(base + OFFSET_GPIO_INTEN);
+}
+
+static inline unsigned int FH_GPIO_GetInterruptStatus(void __iomem *base)
+{
+ return readl(base + OFFSET_GPIO_INTSTATUS);
+}
+
+static inline void FH_GPIO_ClearInterrupt(void __iomem *base, int bit)
+{
+ unsigned int reg;
+
+ reg = readl(base + OFFSET_GPIO_PORTA_EOI);
+ reg |= (1 << bit);
+ writel(reg, base + OFFSET_GPIO_PORTA_EOI);
+}
+
+
+static inline void __iomem *gpio_to_base(unsigned int gpio)
+{
+ void __iomem *base;
+ gpio = gpio / 32;
+
+ switch (gpio) {
+ case 0:
+ base = fh_gpio0->base;
+ break;
+ case 1:
+ base = fh_gpio1->base;
+ break;
+ case 2:
+ base = fh_gpio2->base;
+ break;
+ case 3:
+ base = fh_gpio3->base;
+ break;
+ default:
+ pr_err("ERROR: incorrect GPIO num\n");
+ base = NULL;
+ break;
+ }
+
+ return base;
+}
+
+static int _set_gpio_irq_type(unsigned int gpio, unsigned int type)
+{
+ u32 int_type, int_polarity;
+ u32 bit = gpio % 32;
+ void __iomem *base;
+ struct fh_gpio_chip *fh_gpio = NULL;
+
+ switch (gpio / 32) {
+ case 0:
+ fh_gpio = fh_gpio0;
+ break;
+ case 1:
+ fh_gpio = fh_gpio1;
+ break;
+ case 2:
+ fh_gpio = fh_gpio2;
+ break;
+ case 3:
+ fh_gpio = fh_gpio3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ base = gpio_to_base(gpio);
+ switch (type & IRQF_TRIGGER_MASK) {
+ case IRQ_TYPE_EDGE_BOTH:
+ if (!fh_gpio->type) {
+ int_type = GPIO_INT_TYPE_EDGE;
+ /* toggle trigger */
+ if (FH_GPIO_GetValue(base, bit))
+ int_polarity = GPIO_INT_POL_LOW;
+ else
+ int_polarity = GPIO_INT_POL_HIGH;
+ }
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ int_type = GPIO_INT_TYPE_EDGE;
+ int_polarity = GPIO_INT_POL_HIGH;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ int_type = GPIO_INT_TYPE_EDGE;
+ int_polarity = GPIO_INT_POL_LOW;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ int_type = GPIO_INT_TYPE_LEVEL;
+ int_polarity = GPIO_INT_POL_HIGH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ int_type = GPIO_INT_TYPE_LEVEL;
+ int_polarity = GPIO_INT_POL_LOW;
+ break;
+ case IRQ_TYPE_NONE:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ if ((type & IRQF_TRIGGER_MASK) == IRQ_TYPE_EDGE_BOTH) {
+ if (fh_gpio->type)
+ FH_GPIO_Set_BothInterrupt_enable(base, bit);
+ else {
+ FH_GPIO_SetInterruptType(base, bit, int_type);
+ FH_GPIO_SetInterruptPolarity(base, bit, int_polarity);
+ }
+ } else {
+ FH_GPIO_Set_BothInterrupt_disable(base, bit);
+ FH_GPIO_SetInterruptType(base, bit, int_type);
+ FH_GPIO_SetInterruptPolarity(base, bit, int_polarity);
+ }
+
+ return 0;
+}
+
+int fh_set_gpio_irq(struct gpio_irq_info *info)
+{
+ void __iomem *base;
+
+ base = gpio_to_base(info->irq_gpio);
+ return _set_gpio_irq_type(info->irq_gpio, info->irq_type);
+}
+EXPORT_SYMBOL(fh_set_gpio_irq);
+
+void fh_irq_enable(unsigned int gpio)
+{
+ void __iomem *base;
+ int gpio_num = gpio % 32;
+
+ base = gpio_to_base(gpio);
+
+ FH_GPIO_EnableInterrupt(base, gpio_num, 1);
+}
+EXPORT_SYMBOL(fh_irq_enable);
+
+void fh_irq_disable(unsigned int gpio)
+{
+ void __iomem *base;
+ int gpio_num = gpio % 32;
+
+ base = gpio_to_base(gpio);
+ FH_GPIO_EnableInterrupt(base, gpio_num, 0);
+}
+EXPORT_SYMBOL(fh_irq_disable);
+
+void fh_clear_gpio_irq(int gpio_id)
+{
+ void __iomem *base;
+ int gpio_num = gpio_id % 32;
+
+ base = gpio_to_base(gpio_id);
+ FH_GPIO_ClearInterrupt(base, gpio_num);
+}
+EXPORT_SYMBOL(fh_clear_gpio_irq);
+
+static inline void __iomem *irq_to_controller(struct irq_data *d)
+{
+ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d);
+
+ return fh_gpio->base;
+}
+
+static void gpio_irq_ack(struct irq_data *d)
+{
+ void __iomem *base;
+
+ unsigned int gpio_bit = d->hwirq;
+ /* struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); */
+
+ base = irq_to_controller(d);
+ FH_GPIO_ClearInterrupt(base, gpio_bit);
+}
+
+static void gpio_irq_enable(struct irq_data *d)
+{
+ void __iomem *base;
+
+ unsigned gpio_bit = d->hwirq;
+ /* struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); */
+
+ base = irq_to_controller(d);
+ FH_GPIO_EnableInterrupt(base, gpio_bit, 1);
+}
+
+static void gpio_irq_disable(struct irq_data *d)
+{
+ void __iomem *base;
+
+ unsigned gpio_bit = d->hwirq;
+ /* struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); */
+
+ base = irq_to_controller(d);
+ FH_GPIO_EnableInterrupt(base, gpio_bit, 0);
+}
+
+static void gpio_irq_mask(struct irq_data *d)
+{
+ void __iomem *base;
+
+ unsigned gpio_bit = d->hwirq;
+ /* struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); */
+
+ base = irq_to_controller(d);
+ FH_GPIO_EnableInterruptMask(base, gpio_bit, 1);
+}
+
+static void gpio_irq_unmask(struct irq_data *d)
+{
+ void __iomem *base;
+
+ unsigned int gpio_bit = d->hwirq;
+ /* struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d); */
+
+ base = irq_to_controller(d);
+ FH_GPIO_EnableInterruptMask(base, gpio_bit, 0);
+}
+
+static int gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+ void __iomem *base;
+ unsigned int gpio;
+
+ unsigned gpio_bit = d->hwirq;
+ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d);
+
+ base = irq_to_controller(d);
+ gpio = gpio_bit + fh_gpio->chip.base;
+ return _set_gpio_irq_type(gpio, type);
+}
+
+#ifdef CONFIG_PM
+
+static int gpio_irq_set_wake(struct irq_data *d, unsigned value)
+{
+ int gpio = d->hwirq;
+ struct fh_gpio_chip *fh_gpio = irq_data_get_irq_chip_data(d);
+
+ if (value)
+ fh_gpio->gpio_wakeups |= (1 << gpio);
+ else
+ fh_gpio->gpio_wakeups &= ~(1 << gpio);
+
+ return 0;
+}
+
+void fh_gpio_irq_suspend(void)
+{
+ fh_gpio0->gpio_backups = FH_GPIO_GetEnableInterrupts(fh_gpio0->base);
+ fh_gpio1->gpio_backups = FH_GPIO_GetEnableInterrupts(fh_gpio1->base);
+
+ FH_GPIO_SetEnableInterrupts(fh_gpio0->base, fh_gpio0->gpio_wakeups);
+ FH_GPIO_SetEnableInterrupts(fh_gpio1->base, fh_gpio1->gpio_wakeups);
+}
+
+void fh_gpio_irq_resume(void)
+{
+ FH_GPIO_SetEnableInterrupts(fh_gpio0->base, fh_gpio0->gpio_backups);
+ FH_GPIO_SetEnableInterrupts(fh_gpio1->base, fh_gpio1->gpio_backups);
+}
+
+#else
+#define gpio_irq_set_wake NULL
+#endif
+
+static struct irq_chip gpio_irqchip = {
+ .name = "FH_GPIO_INTC",
+ .irq_ack = gpio_irq_ack,
+ .irq_enable = gpio_irq_enable,
+ .irq_disable = gpio_irq_disable,
+ .irq_mask = gpio_irq_mask,
+ .irq_unmask = gpio_irq_unmask,
+ .irq_set_type = gpio_irq_type,
+ .irq_set_wake = gpio_irq_set_wake,
+};
+
+static void gpio_toggle_trigger(unsigned int gpio, unsigned int offs)
+{
+ u32 int_polarity;
+ int gpio_num = gpio % 32;
+ void __iomem *base = gpio_to_base(gpio);
+
+ if (FH_GPIO_GetValue(base, offs))
+ int_polarity = GPIO_INT_POL_LOW;
+ else
+ int_polarity = GPIO_INT_POL_HIGH;
+
+ FH_GPIO_SetInterruptPolarity(base, gpio_num, int_polarity);
+}
+
+static void gpio_irq_handler(struct irq_desc *desc)
+{
+ struct irq_data *irqdata = irq_desc_get_irq_data(desc);
+ struct irq_chip *irqchip = irq_data_get_irq_chip(irqdata);
+ struct fh_gpio_chip *fh_gpio = irq_desc_get_handler_data(desc);
+ u32 irq_status;
+ int gpio_num;
+
+ chained_irq_enter(irqchip, desc);
+ irq_status = FH_GPIO_GetInterruptStatus(fh_gpio->base);
+
+ if (unlikely(irq_status == 0)) {
+ pr_err("gpio irq status is zero.\n");
+ return;
+ }
+
+ /* temporarily mask (level sensitive) parent IRQ */
+ irqchip->irq_mask(irqdata);
+
+ gpio_num = fls(irq_status) - 1;
+
+ FH_GPIO_ClearInterrupt(fh_gpio->base, gpio_num);
+
+ generic_handle_irq(irq_find_mapping(fh_gpio->irq_domain, gpio_num));
+
+ if ((irq_get_trigger_type(irq_find_mapping(fh_gpio->irq_domain, gpio_num)) & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+ if (!fh_gpio->type)
+ gpio_toggle_trigger((fh_gpio->chip.base + gpio_num), gpio_num);
+
+ irqchip->irq_unmask(irqdata);
+
+ chained_irq_exit(irqchip, desc);
+ /* now it may re-trigger */
+}
+
+/*
+* This lock class tells lockdep that GPIO irqs are in a different
+* category than their parents, so it won't report 0 recursion.
+*/
+static struct lock_class_key gpio_lock_class;
+
+static int fh_gpio_irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq)
+{
+ int ret;
+
+ ret = irq_set_chip_data(irq, d->host_data);
+ if (ret < 0)
+ return ret;
+ irq_set_lockdep_class(irq, &gpio_lock_class);
+ irq_set_chip_and_handler(irq, &gpio_irqchip, handle_simple_irq);
+ irq_set_noprobe(irq);
+
+ return 0;
+
+}
+
+static void fh_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
+{
+ irq_set_chip_and_handler(irq, NULL, NULL);
+ irq_set_chip_data(irq, NULL);
+}
+
+static struct irq_domain_ops fh_gpio_irq_ops = {
+ .map = fh_gpio_irq_map,
+ .unmap = fh_gpio_irq_unmap,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static int fh_gpio_irq_create_domain(struct gpio_chip *c, unsigned offset)
+{
+ struct fh_gpio_chip *chip;
+
+ chip = container_of(c, struct fh_gpio_chip, chip);
+ return irq_create_mapping(chip->irq_domain, offset);
+}
+
+static int chip_to_irq(struct gpio_chip *c, unsigned offset)
+{
+ struct fh_gpio_chip *chip;
+
+ chip = container_of(c, struct fh_gpio_chip, chip);
+ if (offset > chip->chip.ngpio)
+ return -ENXIO;
+ return irq_find_mapping(chip->irq_domain, offset);
+}
+
+static int chip_gpio_get(struct gpio_chip *c, unsigned offset)
+{
+ u32 bit = offset % 32;
+ struct fh_gpio_chip *chip;
+
+ chip = container_of(c, struct fh_gpio_chip, chip);
+ if (offset / 32)
+ return FH_GPIOB_GetValue(chip->base, bit);
+ else
+ return FH_GPIO_GetValue(chip->base, bit);
+}
+
+static void chip_gpio_set(struct gpio_chip *c, unsigned int offset, int val)
+{
+ u32 bit = offset % 32;
+ struct fh_gpio_chip *chip;
+
+ chip = container_of(c, struct fh_gpio_chip, chip);
+ if (offset / 32)
+ FH_GPIOB_SetValue(chip->base, bit, val);
+ else
+ FH_GPIO_SetValue(chip->base, bit, val);
+}
+
+static int chip_direction_input(struct gpio_chip *c, unsigned offset)
+{
+ u32 bit = offset % 32;
+ unsigned long flags;
+ struct fh_gpio_chip *chip;
+
+ chip = container_of(c, struct fh_gpio_chip, chip);
+ spin_lock_irqsave(&chip->lock, flags);
+ if (offset / 32)
+ FH_GPIOB_SetDirection(chip->base, bit, GPIO_DIR_INPUT);
+ else
+ FH_GPIO_SetDirection(chip->base, bit, GPIO_DIR_INPUT);
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
+{
+ u32 bit = offset % 32;
+ unsigned long flags;
+ struct fh_gpio_chip *chip;
+
+ chip = container_of(c, struct fh_gpio_chip, chip);
+ spin_lock_irqsave(&chip->lock, flags);
+ if (offset / 32) {
+ FH_GPIOB_SetDirection(chip->base, bit, GPIO_DIR_OUTPUT);
+ FH_GPIOB_SetValue(chip->base, bit, val);
+ } else {
+ FH_GPIO_SetDirection(chip->base, bit, GPIO_DIR_OUTPUT);
+ FH_GPIO_SetValue(chip->base, bit, val);
+ }
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static int chip_gpio_set_debounce(struct gpio_chip *c, unsigned offset,
+ unsigned int debounce)
+{
+ u32 bit = offset % 32;
+ unsigned long flags;
+ char db_clk_name[16] = {0};
+ struct clk *gpio_clk = NULL;
+ int ret = 0;
+ struct fh_gpio_chip *chip;
+ bool enabled = !!debounce;
+ unsigned int clk_rate = 0;
+
+ sprintf(db_clk_name, "gpio%d_gbclk", (offset / 32));
+ gpio_clk = clk_get(NULL, db_clk_name);
+ if (IS_ERR(gpio_clk))
+ return PTR_ERR(gpio_clk);
+
+ clk_rate = 1000000UL / debounce;
+
+ ret = clk_set_rate(gpio_clk, clk_rate);
+ if (ret) {
+ pr_err("Set GPIO Debounce Clk fail\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(gpio_clk);
+ if (ret) {
+ pr_err("Set GPIO Debounce Clk fail\n");
+ return ret;
+ }
+
+ chip = container_of(c, struct fh_gpio_chip, chip);
+ spin_lock_irqsave(&chip->lock, flags);
+ FH_GPIO_EnableDebounce(chip->base, bit, enabled);
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+void fh_gpio_set(int gpio_id, int value)
+{
+ __gpio_set_value(gpio_id, value);
+}
+EXPORT_SYMBOL(fh_gpio_set);
+
+int fh_gpio_get(int gpio_id, int *value)
+{
+ *value = __gpio_get_value(gpio_id);
+ return 0;
+}
+EXPORT_SYMBOL(fh_gpio_get);
+
+int fh_gpio_reset(int gpio_id)
+{
+ return 0;
+}
+EXPORT_SYMBOL(fh_gpio_reset);
+
+static void fh_gpio_irq_init(struct platform_device *pdev)
+{
+ int i, gpio_irq;
+ struct fh_gpio_chip *plat_data;
+
+ plat_data = pdev->dev.platform_data;
+
+ for (i = 0; i < 32; i++) {
+ gpio_irq = fh_gpio_irq_create_domain(&plat_data->chip, i);
+ irq_set_lockdep_class(gpio_irq, &gpio_lock_class);
+ irq_set_chip_and_handler(gpio_irq, &gpio_irqchip, handle_simple_irq);
+ irq_set_chip_data(gpio_irq, plat_data);
+ }
+
+ irq_set_chained_handler_and_data(plat_data->irq, gpio_irq_handler, plat_data);
+}
+
+static struct of_device_id const fh_gpio_of_match[] = {
+ { .compatible = "fh,fh-gpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fh_gpio_of_match);
+
+static int fh_gpio_probe(struct platform_device *pdev)
+{
+ int err = -EIO;
+ int id;
+ struct fh_gpio_chip *plat_data;
+#ifdef CONFIG_OF
+ int ngpio;
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *res;
+#endif
+
+#ifdef CONFIG_OF
+ match = of_match_device(fh_gpio_of_match, &pdev->dev);
+ if (!match) {
+ pr_info("Failed to find gpio controller\n");
+ return -ENODEV;
+ }
+
+ plat_data = devm_kzalloc(&pdev->dev, sizeof(*plat_data), GFP_KERNEL);
+ if (!plat_data)
+ return -ENOMEM;
+
+ plat_data->chip.of_node = np;
+ /* set up the driver-specific struct */
+ of_property_read_u32(np, "ngpio", &ngpio);
+ plat_data->chip.ngpio = ngpio;
+ of_property_read_u32(np, "base", &plat_data->chip.base);
+ of_property_read_u32(np, "id", &id);
+ of_property_read_u32(np, "trigger-type", &plat_data->type);
+
+ plat_data->irq = irq_of_parse_and_map(np, 0);
+ if (plat_data->irq < 0) {
+ dev_err(&pdev->dev, "gpio interrupt is not available.\n");
+ return plat_data->irq;
+ }
+
+ plat_data->base = of_iomap(np, 0);
+ if (plat_data->base == NULL) {
+ err = -ENXIO;
+ goto release_irq;
+ }
+
+ plat_data->irq_domain = irq_domain_add_linear(np, plat_data->chip.ngpio, &fh_gpio_irq_ops, plat_data);
+
+ if (!plat_data->irq_domain) {
+ dev_err(&pdev->dev, "Couldn't allocate IRQ domain\n");
+ err = -ENXIO;
+ goto release_io;
+ }
+#else
+ plat_data = pdev->dev.platform_data;
+
+ id = pdev->id;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ return err;
+ }
+
+ plat_data->irq = irq_create_mapping(NULL, platform_get_irq(pdev, 0));
+ if (plat_data->irq < 0) {
+ dev_err(&pdev->dev, "gpio interrupt is not available.\n");
+ return plat_data->irq;
+ }
+
+ plat_data->base = ioremap(res->start, resource_size(res));
+ if (plat_data->base == NULL) {
+ err = -ENXIO;
+ goto release_irq;
+ }
+
+ plat_data->irq_domain = irq_domain_add_linear(NULL,
+ plat_data->chip.ngpio, &fh_gpio_irq_ops, plat_data);
+
+ if (!plat_data->irq_domain) {
+ dev_err(&pdev->dev, "Couldn't allocate IRQ domain\n");
+ err = -ENXIO;
+ goto release_io;
+ }
+#endif
+
+ plat_data->chip.direction_input = chip_direction_input;
+ plat_data->chip.direction_output = chip_direction_output;
+ plat_data->chip.get = chip_gpio_get;
+ plat_data->chip.set = chip_gpio_set;
+ plat_data->chip.to_irq = chip_to_irq;
+ plat_data->chip.set_debounce = chip_gpio_set_debounce;
+
+ switch (id) {
+ case 0:
+ fh_gpio0 = plat_data;
+ plat_data->chip.names = NULL;
+ break;
+ case 1:
+ fh_gpio1 = plat_data;
+ plat_data->chip.names = NULL;
+ break;
+ case 2:
+ fh_gpio2 = plat_data;
+ plat_data->chip.names = NULL;
+ break;
+ case 3:
+ fh_gpio3 = plat_data;
+ plat_data->chip.names = NULL;
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown GPIO Controller\n");
+ err = -ENXIO;
+ goto release_domain;
+ }
+
+ plat_data->pdev = pdev;
+ spin_lock_init(&plat_data->lock);
+ pdev->dev.platform_data = plat_data;
+ /* finally, register with the generic GPIO API */
+ err = gpiochip_add(&plat_data->chip);
+ if (err) {
+ pr_err("GPIO support load fail.\n");
+ goto release_domain;
+ }
+
+ fh_gpio_irq_init(pdev);
+ pr_debug("GPIO support successfully loaded.\n\tBase Addr: 0x%p\n",
+ plat_data->base);
+
+ return 0;
+
+release_domain:
+ irq_domain_remove(plat_data->irq_domain);
+release_io:
+ iounmap(plat_data->base);
+release_irq:
+ irq_dispose_mapping(plat_data->irq);
+ free_irq(plat_data->irq, plat_data);
+
+ return err;
+}
+
+static int fh_gpio_remove(struct platform_device *pdev)
+{
+ struct fh_gpio_chip *plat_data;
+
+ plat_data = pdev->dev.platform_data;
+
+ gpiochip_remove(&plat_data->chip);
+ irq_domain_remove(plat_data->irq_domain);
+ iounmap(plat_data->base);
+
+ return 0;
+}
+
+static struct platform_driver fh_gpio_driver = {
+ .driver = {
+ .name = GPIO_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = fh_gpio_of_match,
+ },
+ .probe = fh_gpio_probe,
+ .remove = fh_gpio_remove,
+};
+
+static int __init fh_gpio_init(void)
+{
+ return platform_driver_register(&fh_gpio_driver);
+}
+
+static void __exit fh_gpio_exit(void)
+{
+ platform_driver_unregister(&fh_gpio_driver);
+}
+
+module_init(fh_gpio_init);
+module_exit(fh_gpio_exit);
+
+MODULE_AUTHOR("QIN");
+MODULE_DESCRIPTION("Fullhan GPIO device driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform: FH");
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 4b44dd97..435ca2e6 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -609,7 +609,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
dev = device_create_with_groups(&gpio_class, &gdev->dev,
MKDEV(0, 0), data, gpio_groups,
- ioname ? ioname : "gpio%u",
+ ioname ? ioname : "GPIO%u",
desc_to_gpio(desc));
if (IS_ERR(dev)) {
status = PTR_ERR(dev);
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 86b2b578..b126285c 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for the HID driver
#
-hid-y := hid-core.o hid-input.o
+hid-$(CONFIG_HID) := hid-core.o hid-input.o
hid-$(CONFIG_DEBUG_FS) += hid-debug.o
obj-$(CONFIG_HID) += hid.o
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d252276f..83e148c1 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -343,6 +343,16 @@ config I2C_AT91
the latency to fill the transmission register is too long. If you
are facing this situation, use the i2c-gpio driver.
+config I2C_FH_INTERRUPT
+ tristate "FH I2C Driver with Interrupt"
+ help
+ This supports the use of the I2C interface on Fullhan
+ processors.
+
+ Only master mode is supported.
+
+ This driver can also be built as a module. If so, the module
+ will be called
config I2C_AU1550
tristate "Au1550/Au1200/Au1300 SMBus interface"
depends on MIPS_ALCHEMY
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 29764cc2..fe3c73e8 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -121,5 +121,6 @@ obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
+obj-$(CONFIG_I2C_FH_INTERRUPT) += i2c_fh_interrupt.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff --git a/drivers/i2c/busses/i2c_fh_interrupt.c b/drivers/i2c/busses/i2c_fh_interrupt.c
new file mode 100644
index 00000000..ee0b620c
--- /dev/null
+++ b/drivers/i2c/busses/i2c_fh_interrupt.c
@@ -0,0 +1,1072 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+/* #define FH_I2C_DEBUG */
+
+#ifdef FH_I2C_DEBUG
+#define PRINT_DBG(fmt, args...) printk(fmt, ## args)
+#else
+#define PRINT_DBG(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * Registers offset
+ */
+/*I2C*/
+#define REG_I2C_CON (0x0000)
+#define REG_I2C_TAR (0x0004)
+#define REG_I2C_SAR (0x0008)
+#define REG_I2C_HS_MADDR (0x000C)
+#define REG_I2C_DATA_CMD (0x0010)
+#define REG_I2C_SS_SCL_HCNT (0x0014)
+#define REG_I2C_SS_SCL_LCNT (0x0018)
+#define REG_I2C_FS_SCL_HCNT (0x001C)
+#define REG_I2C_FS_SCL_LCNT (0x0020)
+#define REG_I2C_HS_SCL_HCNT (0x0024)
+#define REG_I2C_HS_SCL_LCNT (0x0028)
+#define REG_I2C_INTR_STAT (0x002c)
+#define REG_I2C_INTR_MASK (0x0030)
+#define REG_I2C_RAW_INTR_STAT (0x0034)
+#define REG_I2C_RX_TL (0x0038)
+#define REG_I2C_TX_TL (0x003c)
+#define REG_I2C_CLR_INTR (0x0040)
+#define REG_I2C_ENABLE (0x006c)
+#define REG_I2C_STATUS (0x0070)
+#define REG_I2C_TXFLR (0x0074)
+#define REG_I2C_RXFLR (0x0078)
+#define REG_I2C_DMA_CR (0x0088)
+#define REG_I2C_DMA_TDLR (0x008c)
+#define REG_I2C_DMA_RDLR (0x0090)
+
+#define DW_IC_INTR_NONE 0x0
+
+#define DW_IC_CON 0x0
+#define DW_IC_TAR 0x4
+#define DW_IC_DATA_CMD 0x10
+#define DW_IC_SS_SCL_HCNT 0x14
+#define DW_IC_SS_SCL_LCNT 0x18
+#define DW_IC_FS_SCL_HCNT 0x1c
+#define DW_IC_FS_SCL_LCNT 0x20
+#define DW_IC_INTR_STAT 0x2c
+#define DW_IC_INTR_MASK 0x30
+#define DW_IC_RAW_INTR_STAT 0x34
+#define DW_IC_RX_TL 0x38
+#define DW_IC_TX_TL 0x3c
+#define DW_IC_CLR_INTR 0x40
+#define DW_IC_CLR_RX_UNDER 0x44
+#define DW_IC_CLR_RX_OVER 0x48
+#define DW_IC_CLR_TX_OVER 0x4c
+#define DW_IC_CLR_RD_REQ 0x50
+#define DW_IC_CLR_TX_ABRT 0x54
+#define DW_IC_CLR_RX_DONE 0x58
+#define DW_IC_CLR_ACTIVITY 0x5c
+#define DW_IC_CLR_STOP_DET 0x60
+#define DW_IC_CLR_START_DET 0x64
+#define DW_IC_CLR_GEN_CALL 0x68
+#define DW_IC_ENABLE 0x6c
+#define DW_IC_STATUS 0x70
+#define DW_IC_TXFLR 0x74
+#define DW_IC_RXFLR 0x78
+#define DW_IC_COMP_PARAM_1 0xf4
+#define DW_IC_TX_ABRT_SOURCE 0x80
+
+#define DW_IC_CON_MASTER 0x1
+#define DW_IC_CON_SPEED_STD 0x2
+#define DW_IC_CON_SPEED_FAST 0x4
+#define DW_IC_CON_10BITADDR_MASTER 0x10
+#define DW_IC_CON_RESTART_EN 0x20
+#define DW_IC_CON_SLAVE_DISABLE 0x40
+
+#define DW_IC_INTR_RX_UNDER 0x001
+#define DW_IC_INTR_RX_OVER 0x002
+#define DW_IC_INTR_RX_FULL 0x004
+#define DW_IC_INTR_TX_OVER 0x008
+#define DW_IC_INTR_TX_EMPTY 0x010
+#define DW_IC_INTR_RD_REQ 0x020
+#define DW_IC_INTR_TX_ABRT 0x040
+#define DW_IC_INTR_RX_DONE 0x080
+#define DW_IC_INTR_ACTIVITY 0x100
+#define DW_IC_INTR_STOP_DET 0x200
+#define DW_IC_INTR_START_DET 0x400
+#define DW_IC_INTR_GEN_CALL 0x800
+
+#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
+ DW_IC_INTR_TX_EMPTY | \
+ DW_IC_INTR_TX_ABRT | \
+ DW_IC_INTR_STOP_DET)
+
+#define DW_IC_STATUS_ACTIVITY 0x1
+#define DW_IC_STATUS_MASTER_ACTIVITY 0x20
+
+#define DW_IC_ERR_TX_ABRT 0x1
+
+/*
+ * status codes
+ */
+#define STATUS_IDLE 0x0
+#define STATUS_WRITE_IN_PROGRESS 0x1
+#define STATUS_READ_IN_PROGRESS 0x2
+
+#define TIMEOUT 20 /* ms */
+
+/*
+ * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register
+ *
+ * only expected abort codes are listed here
+ * refer to the datasheet for the full list
+ */
+#define ABRT_7B_ADDR_NOACK 0
+#define ABRT_10ADDR1_NOACK 1
+#define ABRT_10ADDR2_NOACK 2
+#define ABRT_TXDATA_NOACK 3
+#define ABRT_GCALL_NOACK 4
+#define ABRT_GCALL_READ 5
+#define ABRT_SBYTE_ACKDET 7
+#define ABRT_SBYTE_NORSTRT 9
+#define ABRT_10B_RD_NORSTRT 10
+#define ABRT_MASTER_DIS 11
+#define ARB_LOST 12
+
+#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK)
+#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK)
+#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK)
+#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK)
+#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK)
+#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ)
+#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET)
+#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT)
+#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT)
+#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS)
+#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST)
+
+#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
+ DW_IC_TX_ABRT_10ADDR1_NOACK | \
+ DW_IC_TX_ABRT_10ADDR2_NOACK | \
+ DW_IC_TX_ABRT_TXDATA_NOACK | \
+ DW_IC_TX_ABRT_GCALL_NOACK)
+
+static char *abort_sources[] = {
+ [ABRT_7B_ADDR_NOACK] =
+ "slave address not acknowledged (7bit mode)",
+ [ABRT_10ADDR1_NOACK] =
+ "first address byte not acknowledged (10bit mode)",
+ [ABRT_10ADDR2_NOACK] =
+ "second address byte not acknowledged (10bit mode)",
+ [ABRT_TXDATA_NOACK] =
+ "data not acknowledged",
+ [ABRT_GCALL_NOACK] =
+ "no acknowledgement for a general call",
+ [ABRT_GCALL_READ] =
+ "read after general call",
+ [ABRT_SBYTE_ACKDET] =
+ "start byte acknowledged",
+ [ABRT_SBYTE_NORSTRT] =
+ "trying to send start byte when restart is disabled",
+ [ABRT_10B_RD_NORSTRT] =
+ "trying to read when restart is disabled (10bit mode)",
+ [ABRT_MASTER_DIS] =
+ "trying to use disabled adapter",
+ [ARB_LOST] =
+ "lost arbitration",
+};
+
+enum BUS_STATUS {
+ I2C_BUSY,
+ I2C_IDLE
+};
+enum RESULT {
+ SUCCESS,
+ FAILURE
+};
+enum ENABLE_SET {
+ DISABLE,
+ ENABLE
+};
+enum SPEED_MODE {
+ SSPEED = 1,
+ FSPEED = 2,
+ HSPEED = 3,
+};
+
+/* function Macro */
+#define I2C_GetTransmitFifoLevel(base_addr) (readl(base_addr + \
+ REG_I2C_TXFLR))
+
+#define I2c_GetTxFifoDepth(base_addr) (((readl(base_addr + \
+ DW_IC_COMP_PARAM_1)>>16) & 0xff) + 1)
+
+#define I2c_GetRxFifoDepth(base_addr) (((readl(base_addr + \
+ DW_IC_COMP_PARAM_1)>>8) & 0xff) + 1)
+
+#define I2c_SetDeviceId(base_addr, deviceID) writel(deviceID,\
+ base_addr + REG_I2C_TAR) /* set IIC slave address */
+
+#define I2c_Read(base_addr) (readl(base_addr + REG_I2C_DATA_CMD)&0xff)
+
+#define I2c_SetSsHcnt(base_addr, hcnt) writel(hcnt,\
+ base_addr + DW_IC_SS_SCL_HCNT)
+
+#define I2c_SetSsLcnt(base_addr, lcnt) writel(lcnt,\
+ base_addr + DW_IC_SS_SCL_LCNT)
+
+#define I2c_SetFsHcnt(base_addr, hcnt) writel(hcnt,\
+ base_addr + DW_IC_FS_SCL_HCNT)
+
+#define I2c_SetFsLcnt(base_addr, lcnt) writel(lcnt,\
+ base_addr + DW_IC_FS_SCL_LCNT)
+
+#define I2c_DisEnable(base_addr) writel(DISABLE, base_addr + REG_I2C_ENABLE)
+
+#define I2c_Enable(base_addr) writel(ENABLE, base_addr + REG_I2C_ENABLE)
+
+#define I2c_Write(base_addr, data) writel(data, base_addr + REG_I2C_DATA_CMD)
+
+#define I2c_GetTxTl(base_addr) (readl(base_addr + REG_I2C_TX_TL)&0xff)
+
+#define I2c_GetRxTl(base_addr) (readl(base_addr + REG_I2C_RX_TL)&0xff)
+
+#define I2c_GetRxFLR(base_addr) (readl(base_addr + DW_IC_RXFLR)&0xff)
+
+#define I2c_GetTxFLR(base_addr) (readl(base_addr + DW_IC_TXFLR)&0xff)
+
+#define I2c_SetTxRxTl(base_addr, txtl, rxtl) do {\
+ writel(txtl, base_addr + REG_I2C_TX_TL); \
+ writel(rxtl, base_addr + REG_I2C_RX_TL); \
+ } while (0)
+
+#define I2c_IsActiveMst(base_addr) (readl(base_addr + REG_I2C_STATUS)>>5 & 1)
+
+#define I2c_SetCon(base_addr, config) writel(config, base_addr + REG_I2C_CON)
+
+#define I2c_GetCon(base_addr) readl(base_addr + REG_I2C_CON)
+
+#define I2c_Status(base_addr) readl(base_addr + REG_I2C_STATUS)
+
+#define I2c_SetTar(base_addr, id) writel(id, base_addr + REG_I2C_TAR)
+
+#define I2c_SetIntrMask(base_addr, mask) writel(mask,\
+ base_addr + REG_I2C_INTR_MASK)
+
+#define I2c_ClrIntr(base_addr, mask) readl(base_addr + mask)
+
+#define I2c_GetTxAbrtSource(base_addr) readl(base_addr + DW_IC_TX_ABRT_SOURCE)
+
+#define I2c_TxEmpty(base_addr) (readl(base_addr +\
+ REG_I2C_RAW_INTR_STAT) & M_TX_EMPTY)
+
+#define I2c_RxFull(base_addr) (readl(base_addr +\
+ REG_I2C_RAW_INTR_STAT) & M_RX_FULL)
+
+#define I2c_RxEmpty(base_addr) (readl(base_addr +\
+ REG_I2C_RAW_INTR_STAT) & M_RX_OVER)
+
+/* register define */
+union {
+ struct {
+ unsigned int MASTER_MODE : 1;
+ unsigned int SPEED : 2;
+ unsigned int IC_10BITADDR_SLAVE : 1;
+ unsigned int IC_10BITADDR_MASTER : 1;
+ unsigned int IC_RESTART_EN : 1;
+ unsigned int IC_SLAVE_DISABLE : 1;
+ unsigned int reserved_31_7 : 25;
+ } x;
+ unsigned int dw;
+} Reg_I2c_Con;
+
+/**
+ * struct fh_i2c_dev - private i2c-designware data
+ * @dev: driver model device node
+ * @base: IO registers pointer
+ * @cmd_complete: tx completion indicator
+ * @lock: protect this struct and IO registers
+ * @clk: input reference clock
+ * @cmd_err: run time hadware error code
+ * @msgs: points to an array of messages currently being transferred
+ * @msgs_num: the number of elements in msgs
+ * @msg_write_idx: the element index of the current tx message in the msgs
+ * array
+ * @tx_buf_len: the length of the current tx buffer
+ * @tx_buf: the current tx buffer
+ * @msg_read_idx: the element index of the current rx message in the msgs
+ * array
+ * @rx_buf_len: the length of the current rx buffer
+ * @rx_buf: the current rx buffer
+ * @msg_err: error status of the current transfer
+ * @status: i2c master status, one of STATUS_*
+ * @abort_source: copy of the TX_ABRT_SOURCE register
+ * @irq: interrupt number for the i2c master
+ * @adapter: i2c subsystem adapter node
+ * @tx_fifo_depth: depth of the hardware tx fifo
+ * @rx_fifo_depth: depth of the hardware rx fifo
+ */
+struct fh_i2c_dev {
+ struct device *dev;
+ void __iomem *base;
+ struct completion cmd_complete;
+ struct mutex lock;
+ struct clk *clk;
+ int cmd_err;
+ struct i2c_msg *msgs;
+ int msgs_num;
+ int msg_write_idx;
+ u32 tx_buf_len;
+ u8 *tx_buf;
+ int msg_read_idx;
+ u32 rx_buf_len;
+ u8 *rx_buf;
+ int msg_err;
+ unsigned int status;
+ u32 abort_source;
+ int irq;
+ struct i2c_adapter adapter;
+ unsigned int tx_fifo_depth;
+ unsigned int rx_fifo_depth;
+ char isrname[24];
+};
+
+
+static int i2c_fh_wait_master_not_active(struct fh_i2c_dev *dev)
+{
+ int timeout = 200; /* 2000 us */
+
+ while (I2c_IsActiveMst(dev->base)) {
+ if (timeout <= 0) {
+ dev_warn(dev->dev, "timeout waiting for master not active\n");
+ return -ETIMEDOUT;
+ }
+ timeout--;
+ udelay(10);
+ }
+
+ return 0;
+}
+
+static u32
+i2c_fh_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
+{
+ /*
+ * DesignWare I2C core doesn't seem to have solid strategy to meet
+ * the tHD;STA timing spec. Configuring _HCNT based on tHIGH spec
+ * will result in violation of the tHD;STA spec.
+ */
+ u32 ret = 0;
+
+ if (cond)
+ /*
+ * Conditional expression:
+ *
+ * IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH
+ *
+ * This is based on the DW manuals, and represents an ideal
+ * configuration. The resulting I2C bus speed will be
+ * faster than any of the others.
+ *
+ * If your hardware is free from tHD;STA issue, try this one.
+ */
+ ret = (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset;
+ else
+ /*
+ * Conditional expression:
+ *
+ * IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf)
+ *
+ * This is just experimental rule; the tHD;STA period turned
+ * out to be proportinal to (_HCNT + 3). With this setting,
+ * we could meet both tHIGH and tHD;STA timing specs.
+ *
+ * If unsure, you'd better to take this alternative.
+ *
+ * The reason why we need to take into account "tf" here,
+ * is the same as described in i2c_fh_scl_lcnt().
+ */
+ ret = (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset;
+ return ret;
+}
+
+static u32 i2c_fh_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
+{
+ /*
+ * Conditional expression:
+ *
+ * IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf)
+ *
+ * DW I2C core starts counting the SCL CNTs for the LOW period
+ * of the SCL clock (tLOW) as soon as it pulls the SCL line.
+ * In order to meet the tLOW timing spec, we need to take into
+ * account the fall time of SCL signal (tf). Default tf value
+ * should be 0.3 us, for safety.
+ */
+ return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset;
+}
+
+/**
+ * i2c_fh_init() - initialize the designware i2c master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+static void i2c_fh_init(struct fh_i2c_dev *dev)
+{
+ u32 input_clock_khz = clk_get_rate(dev->clk) / 1000;
+ u32 ic_con, hcnt, lcnt;
+
+ /* Disable the adapter */
+ i2c_fh_wait_master_not_active(dev);
+ I2c_DisEnable(dev->base);
+
+ /* set standard and fast speed deviders for high/low periods */
+
+ /* Standard-mode */
+
+ hcnt = i2c_fh_scl_hcnt(input_clock_khz,
+ 40, /* tHD;STA = tHIGH = 4.0 us */
+ 3, /* tf = 0.3 us */
+ 0, /* 0: DW default, 1: Ideal */
+ 0); /* No offset */
+ lcnt = i2c_fh_scl_lcnt(input_clock_khz,
+ 47, /* tLOW = 4.7 us */
+ 3, /* tf = 0.3 us */
+ 0); /* No offset */
+ I2c_SetSsHcnt(dev->base, hcnt);
+ I2c_SetSsLcnt(dev->base, lcnt);
+ /* pr_info("\tClock: %dkhz, Standard-mode HCNT:LCNT = %d:%d\n", */
+ /* input_clock_khz, hcnt, lcnt); */
+
+ /* Fast-mode */
+ hcnt = i2c_fh_scl_hcnt(input_clock_khz,
+ 6, /* tHD;STA = tHIGH = 0.6 us */
+ 3, /* tf = 0.3 us */
+ 0, /* 0: DW default, 1: Ideal */
+ 0); /* No offset */
+ lcnt = i2c_fh_scl_lcnt(input_clock_khz,
+ 13, /* tLOW = 1.3 us */
+ 3, /* tf = 0.3 us */
+ 0); /* No offset */
+ I2c_SetFsHcnt(dev->base, hcnt);
+ I2c_SetFsLcnt(dev->base, lcnt);
+ /* dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); */
+
+ /* Configure Tx/Rx FIFO threshold levels */
+
+ I2c_SetTxRxTl(dev->base, dev->tx_fifo_depth - 1, 0);
+ /* configure the i2c master */
+ ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
+ DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
+ I2c_SetCon(dev->base, ic_con);
+
+}
+
+/*
+ * Waiting for bus not busy
+ */
+static int i2c_fh_wait_bus_not_busy(struct fh_i2c_dev *dev)
+{
+ int timeout = TIMEOUT;
+
+ while (I2c_IsActiveMst(dev->base)) {
+ if (timeout <= 0) {
+ dev_warn(dev->dev, "timeout waiting for bus ready\n");
+ return -ETIMEDOUT;
+ }
+ timeout--;
+ /* msleep(1); */
+ usleep_range(100, 1000);
+ }
+
+ return 0;
+}
+
+static void i2c_fh_xfer_init(struct fh_i2c_dev *dev)
+{
+ struct i2c_msg *msgs = dev->msgs;
+ u32 ic_con;
+
+ /* Disable the adapter */
+ i2c_fh_wait_master_not_active(dev);
+ I2c_DisEnable(dev->base);
+
+ /* set the slave (target) address */
+ I2c_SetDeviceId(dev->base, msgs[dev->msg_write_idx].addr);
+
+ /* if the slave address is ten bit address, enable 10BITADDR */
+ ic_con = I2c_GetCon(dev->base);
+ if (msgs[dev->msg_write_idx].flags & I2C_M_TEN)
+ ic_con |= DW_IC_CON_10BITADDR_MASTER;
+ else
+ ic_con &= ~DW_IC_CON_10BITADDR_MASTER;
+ I2c_SetCon(dev->base, ic_con);
+
+ /* Enable the adapter */
+ I2c_Enable(dev->base);
+
+ /* Enable interrupts */
+ I2c_SetIntrMask(dev->base, DW_IC_INTR_DEFAULT_MASK);
+
+}
+
+/*
+ * Initiate (and continue) low level master read/write transaction.
+ * This function is only called from i2c_fh_isr, and pumping i2c_msg
+ * messages into the tx buffer. Even if the size of i2c_msg data is
+ * longer than the size of the tx buffer, it handles everything.
+ */
+static void
+i2c_fh_xfer_msg(struct fh_i2c_dev *dev)
+{
+ struct i2c_msg *msgs = dev->msgs;
+ u32 intr_mask, cmd;
+ int tx_limit, rx_limit;
+ u32 addr = msgs[dev->msg_write_idx].addr;
+ u32 buf_len = dev->tx_buf_len;
+ u8 *buf = dev->tx_buf;
+
+ PRINT_DBG("i2c_fh_xfer_msg start, dev->msgs_num: %d\n", dev->msgs_num);
+
+ intr_mask = DW_IC_INTR_DEFAULT_MASK;
+
+ for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
+ /*
+ * if target address has changed, we need to
+ * reprogram the target address in the i2c
+ * adapter when we are done with this transfer
+ */
+ if (msgs[dev->msg_write_idx].addr != addr) {
+ dev_err(dev->dev,
+ "%s: invalid target address\n", __func__);
+ dev->msg_err = -EINVAL;
+ break;
+ }
+
+ if (msgs[dev->msg_write_idx].len == 0) {
+ dev_err(dev->dev,
+ "%s: invalid message length\n", __func__);
+ dev->msg_err = -EINVAL;
+ break;
+ }
+
+ if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
+ /* new i2c_msg */
+ buf = msgs[dev->msg_write_idx].buf;
+ buf_len = msgs[dev->msg_write_idx].len;
+
+ PRINT_DBG("new msg: len: %d, buf: 0x%x\n",
+ buf_len, buf[0]);
+ }
+
+ tx_limit = dev->tx_fifo_depth - I2c_GetTxTl(dev->base);
+ rx_limit = dev->rx_fifo_depth - I2c_GetRxTl(dev->base);
+
+ while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+ if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
+ cmd = 0x100;
+ rx_limit--;
+ } else {
+ cmd = *buf++;
+ }
+
+ tx_limit--; buf_len--;
+
+ if (!buf_len &&
+ ((dev->msg_write_idx == dev->msgs_num - 1) ||
+ (msgs[dev->msg_write_idx].flags &
+ I2C_M_STOP))) {
+ /* 2015-11-8 ar0130 bug fixed */
+ /* 20*1000 about 2 *0.1 ms */
+ /* (for i2c send one byte @ 100KHz) */
+ /* fixme: define MACRO get timeout value; */
+ unsigned int _timeout = 20000;
+
+ while (I2C_GetTransmitFifoLevel(dev->base) &&
+ _timeout--)
+ ;
+ cmd |= 0x200;
+ }
+
+ I2c_Write(dev->base, cmd);
+ }
+ PRINT_DBG("\n");
+
+ dev->tx_buf = buf;
+ dev->tx_buf_len = buf_len;
+
+ if (buf_len == 0) {
+ dev->status &= ~STATUS_WRITE_IN_PROGRESS;
+ } else {
+ /* more bytes to be written */
+ dev->status |= STATUS_WRITE_IN_PROGRESS;
+ break;
+ }
+ }
+
+ /*
+ * If i2c_msg index search is completed, we don't need TX_EMPTY
+ * interrupt any more.
+ */
+
+ if (dev->msg_write_idx == dev->msgs_num)
+ intr_mask &= ~DW_IC_INTR_TX_EMPTY;
+
+ if (dev->msg_err)
+ intr_mask = 0;
+
+ I2c_SetIntrMask(dev->base, intr_mask);
+
+}
+
+static void
+i2c_fh_read(struct fh_i2c_dev *dev)
+{
+ struct i2c_msg *msgs = dev->msgs;
+ int rx_valid;
+
+ for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
+ u32 len;
+ u8 *buf;
+
+ if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
+ continue;
+
+ if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
+ len = msgs[dev->msg_read_idx].len;
+ buf = msgs[dev->msg_read_idx].buf;
+ } else {
+ PRINT_DBG("STATUS_READ_IN_PROGRESS\n");
+ len = dev->rx_buf_len;
+ buf = dev->rx_buf;
+ }
+
+ rx_valid = I2c_GetRxFLR(dev->base);
+
+ if (rx_valid == 0)
+ PRINT_DBG("rx_valid == 0\n");
+
+ for (; len > 0 && rx_valid > 0; len--, rx_valid--)
+ *buf++ = I2c_Read(dev->base);
+
+ PRINT_DBG("i2c_fh_read, len: %d, buf[0]: 0x%x\n",
+ msgs[dev->msg_read_idx].len,
+ msgs[dev->msg_read_idx].buf[0]);
+
+ if (len == 0) {
+ dev->status &= ~STATUS_READ_IN_PROGRESS;
+ } else {
+ PRINT_DBG("len > 0\n");
+ dev->status |= STATUS_READ_IN_PROGRESS;
+ dev->rx_buf_len = len;
+ dev->rx_buf = buf;
+ return;
+ }
+ }
+}
+
+static int i2c_fh_handle_tx_abort(struct fh_i2c_dev *dev)
+{
+ unsigned long abort_source = dev->abort_source;
+ int i;
+
+ if (abort_source & DW_IC_TX_ABRT_NOACK) {
+ for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) {
+ pr_err(
+ "%s: %s\n", __func__, abort_sources[i]);
+ }
+ return -EREMOTEIO;
+ }
+
+ for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+ pr_err("%s: %s\n", __func__, abort_sources[i]);
+
+ if (abort_source & DW_IC_TX_ARB_LOST)
+ return -EAGAIN;
+ else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
+ return -EINVAL; /* wrong msgs[] data */
+ else
+ return -EIO;
+}
+
+/*
+ * Prepare controller for a transaction and call i2c_fh_xfer_msg
+ */
+static int
+i2c_fh_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct fh_i2c_dev *dev = i2c_get_adapdata(adap);
+ int ret;
+
+ PRINT_DBG("-------i2c, %s: msgs: %d\n", __func__, num);
+
+ mutex_lock(&dev->lock);
+
+ reinit_completion(&dev->cmd_complete);
+ dev->msgs = msgs;
+ dev->msgs_num = num;
+ dev->cmd_err = 0;
+ dev->msg_write_idx = 0;
+ dev->msg_read_idx = 0;
+ dev->msg_err = 0;
+ dev->status = STATUS_IDLE;
+ dev->abort_source = 0;
+
+ ret = i2c_fh_wait_bus_not_busy(dev);
+ if (ret < 0)
+ goto done;
+
+
+ /* start the transfers */
+ i2c_fh_xfer_init(dev);
+
+ /* wait for tx to complete */
+ ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
+
+ if (ret == 0) {
+ dev_err(dev->dev, "controller timed out\n");
+ i2c_fh_init(dev);
+ ret = -ETIMEDOUT;
+ goto done;
+ } else if (ret < 0)
+ goto done;
+
+ if (dev->msg_err) {
+ PRINT_DBG("dev->msg_err\n");
+ ret = dev->msg_err;
+ goto done;
+ }
+
+ /* no error */
+ if (likely(!dev->cmd_err)) {
+ /* Disable the adapter */
+ i2c_fh_wait_master_not_active(dev);
+ I2c_DisEnable(dev->base);
+ ret = num;
+ goto done;
+ }
+
+ /* We have an error */
+ if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
+ PRINT_DBG("dev->cmd_err == DW_IC_ERR_TX_ABRT\n");
+ ret = i2c_fh_handle_tx_abort(dev);
+ goto done;
+ }
+
+ ret = -EIO;
+
+done:
+ PRINT_DBG("buf: 0x%x\n", dev->msgs[num - 1].buf[0]);
+ mutex_unlock(&dev->lock);
+
+ return ret;
+}
+
+static u32 i2c_fh_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static u32 i2c_fh_read_clear_intrbits(struct fh_i2c_dev *dev)
+{
+ u32 stat;
+
+ /*
+ * The IC_INTR_STAT register just indicates "enabled" interrupts.
+ * Ths unmasked raw version of interrupt status bits are available
+ * in the IC_RAW_INTR_STAT register.
+ *
+ * That is,
+ * stat = readl(IC_INTR_STAT);
+ * equals to,
+ * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
+ *
+ * The raw version might be useful for debugging purposes.
+ */
+ stat = readl(dev->base + DW_IC_INTR_STAT);
+
+ /*
+ * Do not use the IC_CLR_INTR register to clear interrupts, or
+ * you'll miss some interrupts, triggered during the period from
+ * readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
+ *
+ * Instead, use the separately-prepared IC_CLR_* registers.
+ */
+ if (stat & DW_IC_INTR_RX_UNDER)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_RX_UNDER);
+ if (stat & DW_IC_INTR_RX_OVER)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_RX_OVER);
+ if (stat & DW_IC_INTR_TX_OVER)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_TX_OVER);
+ if (stat & DW_IC_INTR_RD_REQ)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_RD_REQ);
+ if (stat & DW_IC_INTR_TX_ABRT) {
+ /*
+ * The IC_TX_ABRT_SOURCE register is cleared whenever
+ * the IC_CLR_TX_ABRT is read. Preserve it beforehand.
+ */
+ dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE);
+ I2c_ClrIntr(dev->base, DW_IC_CLR_TX_ABRT);
+ }
+ if (stat & DW_IC_INTR_RX_DONE)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_RX_DONE);
+ if (stat & DW_IC_INTR_ACTIVITY)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_ACTIVITY);
+ if (stat & DW_IC_INTR_STOP_DET)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_STOP_DET);
+ if (stat & DW_IC_INTR_START_DET)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_START_DET);
+ if (stat & DW_IC_INTR_GEN_CALL)
+ I2c_ClrIntr(dev->base, DW_IC_CLR_GEN_CALL);
+
+ return stat;
+}
+
+/*
+ * Interrupt service routine. This gets called whenever an I2C interrupt
+ * occurs.
+ */
+static irqreturn_t i2c_fh_isr(int this_irq, void *dev_id)
+{
+ struct fh_i2c_dev *dev = dev_id;
+ u32 stat;
+
+ stat = i2c_fh_read_clear_intrbits(dev);
+ PRINT_DBG("-----------i2c, %s: stat=0x%x\n", __func__, stat);
+ if (stat & DW_IC_INTR_TX_ABRT) {
+ PRINT_DBG("DW_IC_INTR_TX_ABRT\n");
+ dev->cmd_err |= DW_IC_ERR_TX_ABRT;
+ dev->status = STATUS_IDLE;
+
+ /*
+ * Anytime TX_ABRT is set, the contents of the tx/rx
+ * buffers are flushed. Make sure to skip them.
+ */
+ I2c_SetIntrMask(dev->base, DW_IC_INTR_NONE);
+ goto tx_aborted;
+ }
+
+ if (stat & DW_IC_INTR_RX_FULL) {
+ PRINT_DBG("i2c_fh_read\n");
+ i2c_fh_read(dev);
+ }
+
+ if (stat & DW_IC_INTR_TX_EMPTY) {
+ PRINT_DBG("i2c_fh_xfer_msg\n");
+ i2c_fh_xfer_msg(dev);
+ }
+
+ /*
+ * No need to modify or disable the interrupt mask here.
+ * i2c_fh_xfer_msg() will take care of it according to
+ * the current transmit status.
+ */
+
+tx_aborted:
+ if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
+ complete(&dev->cmd_complete);
+
+ return IRQ_HANDLED;
+}
+
+static struct i2c_algorithm i2c_fh_algo = {
+ .master_xfer = i2c_fh_xfer,
+ .functionality = i2c_fh_func,
+};
+
+
+static int __init fh_i2c_probe(struct platform_device *pdev)
+{
+ struct fh_i2c_dev *dev;
+ struct i2c_adapter *adap;
+ int r;
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *mem;
+#endif
+
+ int id = 0;
+ char clkname[24] = {0};
+ int err = 0;
+
+
+ pr_info("I2C driver:\n\tplatform registration... ");
+
+
+ /* NOTE: driver uses the static register mapping */
+ dev = kzalloc(sizeof(struct fh_i2c_dev), GFP_KERNEL);
+ if (!dev) {
+ r = -ENOMEM;
+ goto err_return;
+ }
+#ifdef CONFIG_USE_OF
+ id = of_alias_get_id(pdev->dev.of_node, "i2c");
+#else
+ id = pdev->id;
+#endif
+
+ snprintf(clkname, sizeof(clkname), "i2c%d_clk", id);
+ dev->clk = clk_get(NULL, clkname);
+ snprintf(dev->isrname, sizeof(dev->isrname), "i2c-%d", id);
+
+ if (IS_ERR(dev->clk)) {
+ r = -ENODEV;
+ goto err_free_mem;
+ }
+ clk_prepare_enable(dev->clk);
+
+ init_completion(&dev->cmd_complete);
+ mutex_init(&dev->lock);
+ dev->dev = get_device(&pdev->dev);
+ platform_set_drvdata(pdev, dev);
+
+#ifdef CONFIG_USE_OF
+ dev->base = of_iomap(np, 0);
+ dev->irq = irq_of_parse_and_map(np, 0);
+#else
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "no mem resource?\n");
+ r = -EINVAL;
+ goto err_unuse_clocks;
+ }
+ dev->irq = irq_create_mapping(NULL, platform_get_irq(pdev, 0));
+ dev->base = ioremap(mem->start, resource_size(mem));
+#endif
+
+
+ if (dev->base == NULL) {
+ dev_err(&pdev->dev, "failure mapping io resources\n");
+ r = -ENOMEM;
+ goto err_unuse_clocks;
+ }
+ {
+ dev->tx_fifo_depth = I2c_GetTxFifoDepth(dev->base);
+ dev->rx_fifo_depth = I2c_GetRxFifoDepth(dev->base);
+ }
+ i2c_fh_init(dev);
+
+ pr_info("\ttx fifo depth: %d, rx fifo depth: %d\n",
+ dev->tx_fifo_depth, dev->rx_fifo_depth);
+
+ I2c_SetIntrMask(dev->base, DW_IC_INTR_NONE); /* disable IRQ */
+
+ if (dev->irq < 0) {
+ dev_err(&pdev->dev, "no irq resource?\n");
+ r = -ENXIO;
+ goto err_iounmap;
+ }
+
+ err = request_irq(dev->irq, i2c_fh_isr,
+ IRQF_SHARED, dev->isrname, dev);
+
+ if (err) {
+ dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+ r = -ENXIO;
+ goto err_iounmap;
+ }
+
+ adap = &dev->adapter;
+ i2c_set_adapdata(adap, dev);
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_HWMON;
+ strlcpy(adap->name, "FH I2C adapter",
+ sizeof(adap->name));
+ adap->algo = &i2c_fh_algo;
+ adap->dev.parent = &pdev->dev;
+
+ adap->nr = id;
+#ifdef CONFIG_USE_OF
+ adap->dev.of_node = np;
+#endif
+ r = i2c_add_numbered_adapter(adap);
+ if (r) {
+ dev_err(&pdev->dev, "failure adding adapter\n");
+ goto err_free_irq;
+ }
+
+ pr_info("\t%s - (dev. name: %s id: %d, IRQ #%d\n"
+ "\t\tIO base addr: 0x%p)\n", "I2C", pdev->name,
+ id, dev->irq, dev->base);
+
+ return 0;
+
+err_free_irq:
+ free_irq(dev->irq, dev);
+err_iounmap:
+ iounmap(dev->base);
+err_unuse_clocks:
+ clk_disable_unprepare(dev->clk);
+ clk_put(dev->clk);
+ dev->clk = NULL;
+err_free_mem:
+ put_device(&pdev->dev);
+ kfree(dev);
+err_return:
+ return r;
+}
+
+static int __exit fh_i2c_remove(struct platform_device *pdev)
+{
+ struct fh_i2c_dev *dev = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&dev->adapter);
+ put_device(&pdev->dev);
+
+ clk_disable_unprepare(dev->clk);
+ clk_put(dev->clk);
+
+ dev->clk = NULL;
+ i2c_fh_wait_master_not_active(dev);
+ writel(0, dev->base + DW_IC_ENABLE);
+ free_irq(dev->irq, dev);
+ kfree(dev);
+
+ return 0;
+}
+static const struct of_device_id fh_i2c_of_match[] = {
+ {.compatible = "fh,fh-i2c",},
+ {},
+};
+
+static struct platform_driver fh_i2c_driver = {
+ .remove = __exit_p(fh_i2c_remove),
+ .driver = {
+ .name = "fh_i2c",
+ .owner = THIS_MODULE,
+ .of_match_table = fh_i2c_of_match,
+
+ },
+};
+
+static int __init fh_i2c_init_driver(void)
+{
+ return platform_driver_probe(&fh_i2c_driver, fh_i2c_probe);
+}
+module_init(fh_i2c_init_driver);
+
+static void __exit fh_i2c_exit_driver(void)
+{
+ platform_driver_unregister(&fh_i2c_driver);
+}
+module_exit(fh_i2c_exit_driver);
+
+MODULE_AUTHOR("QIN");
+MODULE_ALIAS("platform:fh");
+MODULE_DESCRIPTION("fullhan i2c driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 910cb5e2..8fde663f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -115,6 +115,13 @@ config DW_APB_ICTL
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
+config FULLHAN_INTC
+ bool
+ select IRQ_DOMAIN
+ select SPARSE_IRQ
+ select MULTI_IRQ_HANDLER
+
+
config HISILICON_IRQ_MBIGEN
bool
select ARM_GIC_V3
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index e4dbfc85..45583527 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_IRQ_MXS) += irq-mxs.o
obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
+obj-$(CONFIG_FULLHAN_INTC) += irq-fh.o
obj-$(CONFIG_METAG) += irq-metag-ext.o
obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o
diff --git a/drivers/irqchip/irq-fh.c b/drivers/irqchip/irq-fh.c
new file mode 100644
index 00000000..abade53d
--- /dev/null
+++ b/drivers/irqchip/irq-fh.c
@@ -0,0 +1,218 @@
+/*
+ * FH irq subsystem
+ *
+ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/stmp_device.h>
+#include <asm/exception.h>
+
+#include <linux/irqchip.h>
+
+#define OFFSET_IRQ_EN_LOW (0x0000)
+#define OFFSET_IRQ_EN_HIGH (0x0004)
+#define OFFSET_IRQ_IRQMASK_LOW (0x0008)
+#define OFFSET_IRQ_IRQMASK_HIGH (0x000C)
+#define OFFSET_IRQ_IRQFORCE_LOW (0x0010)
+#define OFFSET_IRQ_IRQFORCE_HIGH (0x0014)
+#define OFFSET_IRQ_RAWSTATUS_LOW (0x0018)
+#define OFFSET_IRQ_RAWSTATUS_HIGH (0x001C)
+#define OFFSET_IRQ_STATUS_LOW (0x0020)
+#define OFFSET_IRQ_STATUS_HIGH (0x0024)
+#define OFFSET_IRQ_MASKSTATUS_LOW (0x0028)
+#define OFFSET_IRQ_MASKSTATUS_HIGH (0x002C)
+#define OFFSET_IRQ_FINSTATUS_LOW (0x0030)
+#define OFFSET_IRQ_FINSTATUS_HIGH (0x0034)
+#define OFFSET_FIQ_EN_LOW (0x02C0)
+#define OFFSET_FIQ_EN_HIGH (0x02C4)
+#define OFFSET_FIQ_FIQMASK_LOW (0x02C8)
+#define OFFSET_FIQ_FIQMASK_HIGH (0x02CC)
+#define OFFSET_FIQ_FIQFORCE_LOW (0x02D0)
+#define OFFSET_FIQ_FIQFORCE_HIGH (0x02D4)
+#define OFFSET_FIQ_RAWSTATUS_LOW (0x02D8)
+#define OFFSET_FIQ_RAWSTATUS_HIGH (0x02DC)
+#define OFFSET_FIQ_STATUS_LOW (0x02E0)
+#define OFFSET_FIQ_STATUS_HIGH (0x02E4)
+#define OFFSET_FIQ_FINSTATUS_LOW (0x02E8)
+#define OFFSET_FIQ_FINSTATUS_HIGH (0x02EC)
+
+#define FH_INTC_NUM_IRQS 64
+
+static void __iomem *fh_intc_base;
+static struct irq_domain *fh_intc_domain;
+
+static int fh_intc_set_type(struct irq_data *d, unsigned int type)
+{
+ // only support level high
+ irqd_set_trigger_type(d, IRQF_TRIGGER_HIGH);
+ return 0;
+}
+
+static void fh_intc_enable_irq(struct irq_data *d)
+{
+ u32 reg;
+
+ if (d->hwirq > 31) {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_EN_HIGH);
+ reg |= 1 << (d->hwirq - 32);
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_EN_HIGH);
+
+ } else {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_EN_LOW);
+ reg |= 1 << d->hwirq;
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_EN_LOW);
+ }
+}
+
+static void fh_intc_disable_irq(struct irq_data *d)
+{
+ u32 reg;
+
+ if (d->hwirq > 31) {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_EN_HIGH);
+ reg &= ~(1 << (d->hwirq - 32));
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_EN_HIGH);
+
+ } else {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_EN_LOW);
+ reg &= ~(1 << d->hwirq);
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_EN_LOW);
+ }
+}
+
+static void fh_intc_mask_irq(struct irq_data *d)
+{
+ u32 reg;
+
+ if (d->hwirq > 31) {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_IRQMASK_HIGH);
+ reg |= 1 << (d->hwirq - 32);
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_IRQMASK_HIGH);
+
+ } else {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_IRQMASK_LOW);
+ reg |= 1 << d->hwirq;
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_IRQMASK_LOW);
+ }
+}
+
+static void fh_intc_unmask_irq(struct irq_data *d)
+{
+ u32 reg;
+
+ if (d->hwirq > 31) {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_IRQMASK_HIGH);
+ reg &= ~(1 << (d->hwirq - 32));
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_IRQMASK_HIGH);
+
+ } else {
+ reg = __raw_readl(fh_intc_base + OFFSET_IRQ_IRQMASK_LOW);
+ reg &= ~(1 << d->hwirq);
+ __raw_writel(reg, fh_intc_base + OFFSET_IRQ_IRQMASK_LOW);
+ }
+}
+
+static struct irq_chip fh_intc_chip = {
+ .irq_mask = fh_intc_mask_irq,
+ .irq_unmask = fh_intc_unmask_irq,
+ .irq_enable = fh_intc_enable_irq,
+ .irq_disable = fh_intc_disable_irq,
+ .irq_set_type = fh_intc_set_type,
+
+};
+
+asmlinkage void __exception_irq_entry fh_intc_handle_irq(struct pt_regs *regs)
+{
+ u32 irqnr;
+
+ irqnr = find_first_bit(fh_intc_base + OFFSET_IRQ_FINSTATUS_LOW, 64);
+
+ handle_domain_irq(fh_intc_domain, irqnr, regs);
+
+}
+
+static int fh_irq_domain_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct irq_data *data;
+
+
+ irq_set_chip_and_handler(virq, &fh_intc_chip, handle_level_irq);
+ /* give a default trigger type */
+ data = irq_domain_get_irq_data(d, virq);
+ irqd_set_trigger_type(data, IRQF_TRIGGER_HIGH);
+
+ return 0;
+}
+
+static struct irq_domain_ops fh_irq_domain_ops = {
+ .map = fh_irq_domain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+static void fh_intc_hw_init(void)
+{
+ WARN_ON(!fh_intc_base);
+
+ __raw_writel(0, fh_intc_base + OFFSET_IRQ_EN_LOW);
+ __raw_writel(0, fh_intc_base + OFFSET_IRQ_EN_HIGH);
+}
+
+static void fh_intc_create_default_handler(void)
+{
+ irq_set_default_host(fh_intc_domain);
+ set_handle_irq(fh_intc_handle_irq);
+}
+
+static int __init fh_intc_of_init(struct device_node *np,
+ struct device_node *interrupt_parent)
+{
+ fh_intc_base = of_iomap(np, 0);
+
+ fh_intc_hw_init();
+
+ fh_intc_domain = irq_domain_add_linear(np, FH_INTC_NUM_IRQS,
+ &fh_irq_domain_ops, NULL);
+
+ fh_intc_create_default_handler();
+
+ return fh_intc_domain ? 0 : -ENODEV;
+}
+IRQCHIP_DECLARE(fh, "fh,fh-intc", fh_intc_of_init);
+
+
+#ifndef CONFIG_USE_OF
+void __init fh_intc_init_no_of(unsigned int iovbase)
+{
+ int irq_base;
+
+ fh_intc_base = (void *)iovbase;
+
+ fh_intc_hw_init();
+
+ irq_base = irq_alloc_descs(-1, 0, FH_INTC_NUM_IRQS, 0);
+
+ if (irq_base < 0)
+ irq_base = 0;
+
+
+ /* create a legacy host */
+ fh_intc_domain = irq_domain_add_legacy(NULL, FH_INTC_NUM_IRQS,
+ irq_base, 0, &fh_irq_domain_ops, NULL);
+
+
+ fh_intc_create_default_handler();
+}
+#endif
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index d6c404b3..3b26d4e6 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -290,15 +290,14 @@ static int gic_irq_get_irqchip_state(struct irq_data *d,
return 0;
}
+
static int gic_set_type(struct irq_data *d, unsigned int type)
{
void __iomem *base = gic_dist_base(d);
unsigned int gicirq = gic_irq(d);
-
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
return -EINVAL;
-
/* SPIs have restrictions on the supported types */
if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
type != IRQ_TYPE_EDGE_RISING)
@@ -956,6 +955,9 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
struct gic_chip_data *gic = d->host_data;
+#ifdef CONFIG_ARCH_FULLHAN
+ struct irq_data *data;
+#endif
if (hw < 32) {
irq_set_percpu_devid(irq);
@@ -967,6 +969,13 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
handle_fasteoi_irq, NULL, NULL);
irq_set_probe(irq);
}
+
+#ifdef CONFIG_ARCH_FULLHAN
+ /* give a default trigger type */
+ data = irq_domain_get_irq_data(d, irq);
+ irqd_set_trigger_type(data, IRQF_TRIGGER_HIGH);
+#endif
+
return 0;
}
@@ -1034,6 +1043,8 @@ static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
+ .map = gic_irq_domain_map,
+ .unmap = gic_irq_domain_unmap,
.translate = gic_irq_domain_translate,
.alloc = gic_irq_domain_alloc,
.free = irq_domain_free_irqs_top,
@@ -1149,6 +1160,8 @@ static int gic_init_bases(struct gic_chip_data *gic, int irq_start,
goto error;
}
+ irq_set_default_host(gic->domain);
+
gic_dist_init(gic);
ret = gic_cpu_init(gic);
if (ret)
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index 4706628a..f3ea8555 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -612,10 +612,9 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
static int technisat_usb2_get_ir(struct dvb_usb_device *d)
{
struct technisat_usb2_state *state = d->priv;
- u8 *buf = state->buf;
- u8 *b;
- int ret;
struct ir_raw_event ev;
+ u8 *buf = state->buf;
+ int i, ret;
buf[0] = GET_IR_DATA_VENDOR_REQUEST;
buf[1] = 0x08;
@@ -651,27 +650,26 @@ static int technisat_usb2_get_ir(struct dvb_usb_device *d)
return 0; /* no key pressed */
/* decoding */
- b = buf+1;
#if 0
deb_rc("RC: %d ", ret);
debug_dump(b, ret, deb_rc);
+ debug_dump(buf + 1, ret, deb_rc);
#endif
ev.pulse = 0;
- while (1) {
- ev.pulse = !ev.pulse;
- ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000;
- ir_raw_event_store(d->rc_dev, &ev);
-
- b++;
- if (*b == 0xff) {
+ for (i = 1; i < ARRAY_SIZE(state->buf); i++) {
+ if (buf[i] == 0xff) {
ev.pulse = 0;
ev.duration = 888888*2;
ir_raw_event_store(d->rc_dev, &ev);
break;
}
- }
+
+ ev.pulse = !ev.pulse;
+ ev.duration = (buf[i] * FIRMWARE_CLOCK_DIVISOR *
+ FIRMWARE_CLOCK_TICK) / 1000;
+ ir_raw_event_store(d->rc_dev, &ev);
ir_raw_event_handle(d->rc_dev);
@@ -736,7 +734,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
}
}
},
- }},
+ } },
.size_of_priv = 0,
},
},
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index f7ca1fab..de8051d9 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -2065,8 +2065,8 @@ unsigned int vb2_core_poll(struct vb2_queue *q, struct file *file,
* error flag is set.
*/
if (!vb2_is_streaming(q) || q->error)
- return POLLERR;
-
+ /* return POLLERR; */
+ return 0; /* mengqx */
/*
* If this quirk is set and QBUF hasn't been called yet then
* return POLLERR as well. This only affects capture queues, output
@@ -2324,7 +2324,7 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
* else is able to provide this information with the write() operation.
*/
bool copy_timestamp = !read && q->copy_timestamp;
- unsigned index;
+ unsigned int index;
int ret;
dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 52ef8833..e7899b05 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -683,6 +683,8 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
res = POLLPRI;
else if (req_events & POLLPRI)
poll_wait(file, &fh->wait, wait);
+ if (v4l2_event_pending(fh))
+ res = POLLPRI;
}
return res | vb2_core_poll(q, file, wait);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 64971baf..a29e9746 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -4,6 +4,117 @@
menu "Misc devices"
+config FH_DW_I2S
+ tristate "FH DW I2S(master) support"
+ default n
+ help
+ FH DW I2S driver, as the MASTER, generate BICK & LRCLK for slave
+
+config FH_ACW
+ tristate "FH ACW(slave) support"
+ default n
+ help
+ FH ACW I2S driver, as the SLAVE, external clk input is required
+
+config AUDIO_DMA_BUFFER_KB
+ int "Audio DMA buffer size in KB"
+ depends on FH_DW_I2S || FH_ACW
+ default 32
+ help
+ Audio DMA buffer size in KB
+ 16KHz --> 16KB
+ 48KHz --> 32KB
+
+config FH_STEPMOTOR
+ depends on (ARCH_FH865x || ARCH_FH8636 || ARCH_FH8852V101)
+ tristate "FH STEPMOTOR Suppport"
+ default y
+
+config FH_SADC_V1
+ depends on (MACH_FH8856 || MACH_FH8852)
+ tristate "FH SADC support(v1 version)"
+ help
+ To compile this driver as a module, choose M here: the module will
+ be called fh_sadc.
+
+ HW para:10bits precision, 8 channels, 5M clk in.
+ one conversion need almost (12/5M *1)second
+
+config FH_SADC_V2
+ depends on (MACH_FH8626V100)
+ tristate "FH SADC support(v2 version)"
+ help
+ To compile this driver as a module, choose M here: the module will
+ be called fh_sadc.
+
+ HW para:12bits precision, 8 channels, 5M clk in.
+ one conversion need almost (12/5M *1)second
+
+config FH_SADC_V21
+ depends on (MACH_FH8626V100)
+ tristate "FH SADC support(v21 version)"
+ default n
+
+config FH_SADC_V3
+ depends on (ARCH_FH885xV200 || ARCH_FH865x || ARCH_FH8636 || ARCH_FH8852V101)
+ tristate "FH SADC support(v3 version)"
+ help
+ FH885xV200 or later soc version use SADC_V3 version.
+
+ HW para:12bits precision, 8 channels, 5M clk in.
+ one conversion need almost (12/5M *1)second
+choice
+ bool "FH EFUSE driver select"
+ default FH_EFUSE
+
+config FH_EFUSE_TEE
+ tristate "FH EFUSE driver for tee"
+ depends on TEE
+
+config FH_EFUSE
+ tristate "FH EFUSE driver original"
+ help
+ To compile this driver as a module, choose M here: the module will
+ be called fh_efuse.
+
+ HW para:60 bytes could be programmed.
+endchoice
+
+config FH_L2MEM
+ tristate "FH L2MEM allocator"
+ default n
+
+config FH_PINCTRL_MISC_DEV
+ tristate "FH Pinctrl misc device support"
+ default n
+ depends on ! PINCTRL_FULLHAN
+ help
+ To compile this driver as a module, choose M here: the module will
+ be called.
+
+config FH_CLK_MISC
+ tristate "FH clk miscdev support"
+ default n
+ help
+ To compile this driver as a module, choose M here: the module will
+ be called.
+
+if ARCH_FH885xV200 || ARCH_FH865x || ARCH_FH8636 || ARCH_FH8852V101
+config FH_PERF_MON
+ tristate "FH performance monitor"
+ default y
+ help
+ fh performance monitor
+endif
+
+config FH_TSENSOR
+ depends on !(MACH_FH8856 || MACH_FH8852) && RTC_DRV_FH
+ tristate "FH TSENSOR suppport"
+ default n
+ help
+ fullhan tsensor driver, used to get the chip temperature
+
+
config SENSORS_LIS3LV02D
tristate
depends on INPUT
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 2bf79ba4..92d953f8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,6 +53,22 @@ obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
obj-$(CONFIG_CXL_BASE) += cxl/
obj-$(CONFIG_PANEL) += panel.o
+ccflags-y += -I$(srctree)/drivers/tee/tee_api
+
+obj-$(CONFIG_FH_DMAC_MISC) += fh_dma_miscdev.o
+obj-$(CONFIG_FH_ACW) += fh_acw.o
+obj-$(CONFIG_FH_DW_I2S) += fh_dw_i2s.o
+obj-$(CONFIG_FH_SADC_V1) += fh_sadc.o
+obj-$(CONFIG_FH_SADC_V2) += fh_sadc_v2.o
+obj-$(CONFIG_FH_SADC_V3) += fh_sadc_v3.o
+obj-$(CONFIG_FH_EFUSE) += fh_efuse.o
+obj-$(CONFIG_FH_EFUSE_TEE) += fh_efuse_tee.o
+obj-$(CONFIG_FH_PINCTRL_MISC_DEV) += fh_pinctrl_dev.o
+obj-$(CONFIG_FH_CLK_MISC) += fh_clk_miscdev.o
+obj-$(CONFIG_FH_PERF_MON) += fh_perf_mon.o
+obj-$(CONFIG_FH_STEPMOTOR) += fh_stepmotor.o fh_stepmotor_hw.o
+obj-$(CONFIG_FH_TSENSOR) += fh_tsensor.o
+
lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o
diff --git a/drivers/misc/fh_acw.c b/drivers/misc/fh_acw.c
new file mode 100644
index 00000000..ffe4accb
--- /dev/null
+++ b/drivers/misc/fh_acw.c
@@ -0,0 +1,1422 @@
+/**@file
+ * @Copyright (c) 2016 Shanghai Fullhan Microelectronics Co., Ltd.
+ * @brief
+ *
+ * @author fullhan
+ * @date 2016-7-15
+ * @version V1.0
+ * @version V1.1 modify code style
+ * @note: misc audio driver for fh8830 embedded audio codec.
+ * @note History:
+ * @note <author> <time> <version > <desc>
+ * @note
+ * @warning: the codec is fixed to 24 bit, so remember to move the 24 bit data to 16 bit in
+ * application layer, the next version CPU will sovle this bug.
+ */
+
+
+#include <linux/irqreturn.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/poll.h>
+#include <linux/ioctl.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fh_dmac.h>
+#include <mach/pmu.h>
+#include <mach/fh_i2s_plat.h>
+#ifdef CONFIG_USE_OF
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#else
+#include <linux/irqdomain.h>
+#include <mach/pmu.h>
+#endif
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/fh_acw.h>
+
+#define DEVICE_NAME "fh_audio"
+
+#define NR_DESCS_PER_CHANNEL 64
+
+#define FIX_SAMPLE_BIT 32
+
+#define ACW_CTRL 0x0
+#define ACW_TXFIFO_CTRL 0x4
+#define ACW_RXFIFO_CTRL 0x8
+#define ACW_DAT_CTRL 0x0c
+#define ACW_I2S_CTRL 0x10
+#define ACW_TRACK_CTRL 0x14
+#define ACW_DAT_CTRL0 0x18
+#define ACW_DAT_CTRL1 0x1c
+
+#define ACW_REG_DACL_FIFO_OFFSET 0x100
+#define ACW_REG_DACR_FIFO_OFFSET 0x100
+#define ACW_REG_ADC_FIFO_OFFSET 0x200
+
+#define AUDIO_DMA_PREALLOC_SIZE (32*1024)
+
+#define ACW_INTR_RX_UNDERFLOW 0x10000
+#define ACW_INTR_RX_OVERFLOW 0x20000
+#define ACW_INTR_TX_UNDERFLOW 0x40000
+#define ACW_INTR_TX_OVERFLOW 0x80000
+
+// #define FPGA_TEST
+// #define FH_AUDIO_DEBUG
+#ifdef FH_AUDIO_DEBUG
+#define PRINT_AUDIO_DBG(fmt, args...) \
+ do { \
+ pr_info( "FH_AUDIO_DEBUG: "); \
+ pr_info(fmt, ## args); \
+ } while(0)
+#else
+#define PRINT_AUDIO_DBG(fmt, args...) do { } while (0)
+#endif
+
+static const struct file_operations acw_fops;
+
+static struct audio_dev fh_audio_dev = {
+ .channel_assign = {
+ .capture_channel = -1,
+ .playback_channel = -1,
+ },
+ .dma_master = 0,
+ .fh_audio_miscdev = {
+ .fops = &acw_fops,
+ .name = DEVICE_NAME,
+ .minor = MISC_DYNAMIC_MINOR,
+ }
+
+};
+
+static struct {
+ spinlock_t lock;
+ void __iomem *paddr;
+ void __iomem *vaddr;
+ struct clk *clk;
+ struct clk *acodec_pclk;
+ struct clk *acodec_mclk;
+ int irq;
+} fh_audio_module;
+
+static struct infor_record_t infor_record;
+
+//#define STERO
+static struct fh_audio_dma *dma_rx_transfer = NULL;
+static struct fh_audio_dma *dma_tx_transfer = NULL;
+#ifdef STERO
+static struct fh_audio_dma *dma_tx_right_transfer = NULL;
+#endif
+static struct work_struct playback_wq;
+
+
+#ifdef STERO
+static void fh_acw_tx_right_dma_done(void *arg);
+#define TX_RIGHT_CHANNEL_DMA_CHANNEL 0
+#endif
+static void fh_acw_tx_dma_done(void *arg);
+static void fh_acw_rx_dma_done(void *arg);
+static bool fh_acw_dma_chan_filter(struct dma_chan *chan, void *filter_param);
+
+static void fh_acw_stop_playback(struct fh_audio_cfg *audio_config)
+{
+ unsigned int status;
+
+ if(audio_config->playback.state == STATE_STOP) {
+ return;
+ }
+ audio_config->playback.state = STATE_STOP;
+ status = readl(fh_audio_module.vaddr + ACW_CTRL);
+ status &=(~(1<<29));
+ writel(status, fh_audio_module.vaddr + ACW_CTRL);//tx fifo disable
+ fh_dma_cyclic_stop(dma_tx_transfer->chan);
+ fh_dma_cyclic_free(dma_tx_transfer->chan);
+#ifdef STERO
+ fh_dma_cyclic_stop(dma_tx_right_transfer->chan);
+ fh_dma_cyclic_free(dma_tx_right_transfer->chan);
+#endif
+ up(&audio_config->sem_playback);
+}
+
+static void fh_acw_stop_capture(struct fh_audio_cfg *audio_config)
+{
+ u32 rx_status, status;
+
+ if(audio_config->capture.state == STATE_STOP) {
+ return;
+ }
+ rx_status = readl(fh_audio_module.vaddr + ACW_RXFIFO_CTRL);//clear rx fifo
+ rx_status = rx_status|(1<<4);
+ writel(rx_status,fh_audio_module.vaddr + ACW_RXFIFO_CTRL);
+
+ audio_config->capture.state = STATE_STOP;
+
+ status = readl(fh_audio_module.vaddr + ACW_CTRL);
+ status &=(~(1<<28));
+ writel(status, fh_audio_module.vaddr + ACW_CTRL);//tx fifo disable
+
+ fh_dma_cyclic_stop(dma_rx_transfer->chan);
+ fh_dma_cyclic_free(dma_rx_transfer->chan);
+ up(&audio_config->sem_capture);
+}
+
+static void init_audio(enum audio_type type,struct fh_audio_cfg *audio_config)
+{
+#ifndef CONFIG_MACH_FH8830_FPGA
+ // int reg;
+// reg = readl(fh_audio_module.vaddr + ACW_CTRL);
+// if ((reg & 0x80000000) == 0)
+// {
+// writel(0x80000000, fh_audio_module.vaddr + ACW_CTRL);/*enable audio*/
+// }
+// reg = readl(fh_audio_module.vaddr + ACW_MISC_CTRL);
+// if (0x40400 != reg)
+// {
+// writel(0x40400,fh_audio_module.vaddr + ACW_MISC_CTRL);/*misc ctl*/
+// }
+// if (capture == type)
+// {
+// writel(0x61141b06,fh_audio_module.vaddr + ACW_ADC_PATH_CTRL);/*adc cfg*/
+// writel(0x167f2307, fh_audio_module.vaddr + ACW_ADC_ALC_CTRL);/*adc alc*/
+// writel(0, fh_audio_module.vaddr + ACW_RXFIFO_CTRL);/*rx fifo disable*/
+// switch_input_volume(audio_config->capture.cfg.volume);
+// switch_rate(capture, audio_config->capture.cfg.rate);
+// switch_io_type(capture, audio_config->capture.cfg.io_type);
+// }
+// else
+// {
+// writel(0x3b403f09, fh_audio_module.vaddr + ACW_DAC_PATH_CTRL);/*dac cfg*/
+// writel(0, fh_audio_module.vaddr + ACW_TXFIFO_CTRL);/*tx fifo disable*/
+// switch_rate(playback, audio_config->playback.cfg.rate);
+// switch_io_type(playback, audio_config->playback.cfg.io_type);
+// }
+#endif
+
+}
+
+static inline long bytes_to_frames(int frame_bit, int bytes)
+{
+ return bytes * 8 /frame_bit;
+}
+
+static inline long frames_to_bytes(int frame_bit, int frames)
+{
+ return frames * frame_bit / 8;
+}
+
+static int avail_data_len(enum audio_type type,struct fh_audio_cfg *stream)
+{
+ int delta;
+ if (capture == type)
+ {
+ spin_lock(&stream->capture.lock);
+ delta = stream->capture.hw_ptr - stream->capture.appl_ptr;
+ spin_unlock(&stream->capture.lock);
+ if (delta < 0)
+ {
+ delta += stream->capture.size;
+ }
+ return delta;
+ }
+ else
+ {
+ spin_lock(&stream->playback.lock);
+ delta = stream->playback.appl_ptr - stream->playback.hw_ptr;
+ spin_unlock(&stream->playback.lock);
+ if (delta < 0)
+ {
+ delta += stream->playback.size;
+ }
+ return stream->playback.size - delta;
+ }
+}
+
+static int fh_audio_close(struct inode *ip, struct file *fp)
+{
+ struct miscdevice *miscdev = fp->private_data;
+ struct audio_dev *dev = container_of(miscdev, struct audio_dev, fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ int pid;
+
+#ifndef CONFIG_MACH_FH8830_FPGA
+ //disable interrupts
+ u32 reg;
+ reg = readl(fh_audio_module.vaddr + ACW_CTRL);
+ reg &= ~(0x3ff);
+ writel(reg, fh_audio_module.vaddr + ACW_CTRL);
+#endif
+
+ pid= current->tgid;
+ if(infor_record.play_pid == pid)
+ {
+ fh_acw_stop_playback(audio_config);
+
+ }
+ if (infor_record.record_pid==pid)
+ {
+ fh_acw_stop_capture(audio_config);
+ }
+ return 0;
+}
+
+static int register_tx_dma(struct fh_audio_cfg *audio_config)
+{
+ int ret;
+ struct fh_dma_slave *tx_config;
+ int dma_hs_num = fh_audio_dev.dma_tx_hs_num;
+
+ tx_config = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL);
+ if (!tx_config)
+ {
+ return -ENOMEM;
+ }
+#ifdef STERO
+ //right channel
+ struct dma_slave_config *tx_config_right;
+ tx_config_right = kzalloc(sizeof(struct dma_slave_config), GFP_KERNEL);
+ if (!tx_config_right)
+ {
+ return -ENOMEM;
+ }
+ tx_config_right->slave_id = ACI2S_TX_HW_HANDSHAKE;
+ tx_config_right->src_maxburst = FH_DMA_MSIZE_8;
+ tx_config_right->dst_maxburst = FH_DMA_MSIZE_8;
+ tx_config_right->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ tx_config_right->device_fc = TRUE;
+ tx_config_right->dst_addr = ACW_REG_DACR_FIFO_OFFSET;
+
+ dma_tx_right_transfer->cdesc =fh_dma_cyclic_prep(dma_tx_right_transfer->chan,audio_config->playback.addr,
+ audio_config->playback.cfg.buffer_bytes,audio_config->playback.cfg.period_bytes, DMA_TO_DEVICE);
+ if(dma_tx_transfer->cdesc <= 0)
+ {
+ pr_err("cyclic desc err\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+ dma_tx_transfer->cdesc->period_callback = fh_acw_tx_right_dma_done;
+ dma_tx_transfer->cdesc->period_callback_param = audio_config;
+ fh_dma_cyclic_start(dma_tx_right_transfer->chan);
+ if (tx_slave_right)
+ {
+ kfree(tx_slave_right);
+ }
+ /*must set NULL to tell DMA driver that we free the DMA slave*/
+ dma_tx_right_transfer->chan->private = NULL;
+#endif
+
+#ifdef CONFIG_FH_DMAC
+ tx_config->cfg_hi = FHC_CFGH_DST_PER(dma_hs_num);
+#else
+ tx_config->cfg_hi = dma_hs_num;
+#endif
+
+ tx_config->dst_msize = FH_DMA_MSIZE_8;
+ tx_config->src_msize = FH_DMA_MSIZE_8;
+ tx_config->reg_width = FH_DMA_SLAVE_WIDTH_32BIT;
+ tx_config->fc = FH_DMA_FC_D_M2P;
+ tx_config->tx_reg = (u32)fh_audio_module.paddr + ACW_REG_DACL_FIFO_OFFSET;
+ tx_config->src_master = 0;
+ tx_config->dst_master = fh_audio_dev.dma_master;
+
+ dma_tx_transfer->chan->private = tx_config;
+ if ((audio_config->playback.cfg.buffer_bytes < audio_config->playback.cfg.period_bytes) ||
+ (audio_config->playback.cfg.buffer_bytes <= 0) || (audio_config->playback.cfg.period_bytes <= 0) ||
+ (audio_config->playback.cfg.buffer_bytes/audio_config->playback.cfg.period_bytes > NR_DESCS_PER_CHANNEL))
+ {
+ pr_err( "buffer_size and period_size are invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ dma_tx_transfer->cdesc =fh_dma_cyclic_prep(dma_tx_transfer->chan,audio_config->playback.addr,
+ audio_config->playback.cfg.buffer_bytes,audio_config->playback.cfg.period_bytes, DMA_MEM_TO_DEV);
+ if(dma_tx_transfer->cdesc <= 0)
+ {
+ pr_err( "cyclic desc err\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+ dma_tx_transfer->cdesc->period_callback = fh_acw_tx_dma_done;
+ dma_tx_transfer->cdesc->period_callback_param = audio_config;
+ fh_dma_cyclic_start(dma_tx_transfer->chan);
+ if (tx_config)
+ {
+ kfree(tx_config);
+ }
+ /*must set NULL to tell DMA driver that we free the DMA slave*/
+ dma_tx_transfer->chan->private = NULL;
+ return 0;
+fail:
+ return ret;
+}
+
+static int register_rx_dma(struct fh_audio_cfg *audio_config)
+{
+ int ret,status;
+
+ struct fh_dma_slave *rx_config;
+ int dma_hs_num = fh_audio_dev.dma_rx_hs_num;
+ rx_config = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL);
+ if (!rx_config)
+ {
+ return -ENOMEM;
+ }
+#ifdef CONFIG_FH_DMAC
+ rx_config->cfg_hi = FHC_CFGH_SRC_PER(dma_hs_num);
+#else
+ rx_config->cfg_hi = dma_hs_num;
+#endif
+ rx_config->dst_msize = FH_DMA_MSIZE_8;
+ rx_config->src_msize = FH_DMA_MSIZE_8;
+ rx_config->reg_width = FH_DMA_SLAVE_WIDTH_32BIT;
+ rx_config->fc = FH_DMA_FC_D_P2M;
+ rx_config->rx_reg = (u32)fh_audio_module.paddr + ACW_REG_ADC_FIFO_OFFSET;
+ rx_config->src_master = fh_audio_dev.dma_master;
+ rx_config->dst_master = 0;
+
+ dma_rx_transfer->chan->private = rx_config;
+ if ((audio_config->capture.cfg.buffer_bytes < audio_config->capture.cfg.period_bytes) ||
+ (audio_config->capture.cfg.buffer_bytes <= 0) ||(audio_config->capture.cfg.period_bytes <= 0) ||
+ (audio_config->capture.cfg.buffer_bytes/audio_config->capture.cfg.period_bytes > NR_DESCS_PER_CHANNEL))
+ {
+ pr_err( "buffer_size and period_size are invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ dma_rx_transfer->cdesc = fh_dma_cyclic_prep(dma_rx_transfer->chan,audio_config->capture.addr,
+ audio_config->capture.cfg.buffer_bytes, audio_config->capture.cfg.period_bytes,DMA_DEV_TO_MEM);
+ if(dma_rx_transfer->cdesc <= 0)
+ {
+ pr_err(" cyclic desc err\n");
+ ret = -ENOMEM;
+ goto fail;
+ }
+ dma_rx_transfer->cdesc->period_callback = fh_acw_rx_dma_done;
+ dma_rx_transfer->cdesc->period_callback_param = audio_config;
+ fh_dma_cyclic_start(dma_rx_transfer->chan);
+
+ writel(0x10024,fh_audio_module.vaddr + ACW_RXFIFO_CTRL);/*enable rx fifo*/
+ status = readl(fh_audio_module.vaddr + ACW_CTRL);
+ status |=(1<<28);
+ writel(status, fh_audio_module.vaddr + ACW_CTRL);//tx fifo disable
+ if (rx_config)
+ {
+ kfree(rx_config);
+ }
+ /*must set NULL to tell DMA driver that we free the DMA slave*/
+ dma_rx_transfer->chan->private = NULL;
+ return 0;
+fail:
+ kfree(rx_config);
+ return ret;
+}
+
+
+static void playback_start_wq_handler(struct work_struct *work)
+{
+ int avail;
+ unsigned int status;
+
+ while (1) {
+ if (STATE_STOP == fh_audio_dev.audio_config.playback.state) {
+ return;
+ }
+ avail = avail_data_len(playback, &fh_audio_dev.audio_config);
+ if (avail > fh_audio_dev.audio_config.playback.cfg.period_bytes)
+ msleep(0);
+ else {
+ writel(0x110024, fh_audio_module.vaddr + ACW_TXFIFO_CTRL); //enable tx fifo read enable
+ status = readl(fh_audio_module.vaddr + ACW_CTRL);
+ status |=(1<<29);
+ writel(status, fh_audio_module.vaddr + ACW_CTRL);//tx fifo disable
+
+ break;
+ }
+ }
+}
+
+static int fh_acw_start_playback(struct fh_audio_cfg *audio_config)
+{
+ int ret;
+
+ if (audio_config->playback.state == STATE_RUN) {
+ return 0;
+ }
+
+ if (audio_config->playback.cfg.buffer_bytes > AUDIO_DMA_PREALLOC_SIZE) {
+ pr_err("DMA prealloc buffer is smaller than audio_config->buffer_bytes\n");
+ return -ENOMEM;
+ }
+ memset(audio_config->playback.area, 0, audio_config->playback.cfg.buffer_bytes);
+ audio_config->playback.size = audio_config->playback.cfg.buffer_bytes;
+ audio_config->playback.state = STATE_RUN;
+ ret = register_tx_dma(audio_config);
+ if (ret < 0) {
+ return ret;
+ }
+ INIT_WORK(&playback_wq, playback_start_wq_handler);
+ schedule_work(&playback_wq);
+ return 0;
+}
+
+static int fh_acw_start_capture(struct fh_audio_cfg *audio_config)
+{
+ if(audio_config->capture.state == STATE_RUN)
+ return 0;
+
+ if (audio_config->capture.cfg.buffer_bytes > AUDIO_DMA_PREALLOC_SIZE) {
+ pr_err("DMA prealloc buffer is smaller than audio_config->buffer_bytes\n");
+ return -ENOMEM;
+ }
+ memset(audio_config->capture.area, 0, audio_config->capture.cfg.buffer_bytes);
+ audio_config->capture.size = audio_config->capture.cfg.buffer_bytes;
+
+ audio_config->capture.state = STATE_RUN;
+ return register_rx_dma(audio_config);
+}
+
+
+static void fh_acw_rx_dma_done(void *arg)
+{
+ struct fh_audio_cfg *audio_config = (struct fh_audio_cfg *) arg;
+ struct audio_ptr_t *cap = &audio_config->capture;
+ int hw_pos = 0;
+
+ spin_lock(&cap->lock);
+
+ hw_pos = fh_dma_get_dst_addr(dma_rx_transfer->chan) - cap->addr;
+
+ /* align to period_bytes*/
+ hw_pos -= hw_pos % cap->cfg.period_bytes;
+
+ cap->hw_ptr = hw_pos;
+
+ spin_unlock(&cap->lock);
+ if (waitqueue_active(&audio_config->readqueue)) {
+ int avail = avail_data_len(capture, audio_config);
+
+ if (avail >= cap->cfg.period_bytes)
+ wake_up_interruptible(&audio_config->readqueue);
+ }
+}
+#ifdef STERO
+static void fh_acw_tx_right_dma_done(void *arg)
+{
+ pr_info("tx_right_dam_done\n");
+
+}
+#endif
+
+static void fh_acw_tx_dma_done(void *arg)
+{
+ struct fh_audio_cfg *audio_config = (struct fh_audio_cfg *) arg;
+ struct audio_ptr_t *play = &audio_config->playback;
+ int hw_pos = 0;
+ int delta = 0;
+
+ spin_lock(&play->lock);
+
+ hw_pos = fh_dma_get_src_addr(dma_tx_transfer->chan) - play->addr;
+
+ /* align to period_bytes*/
+ hw_pos -= hw_pos % play->cfg.period_bytes;
+ delta = hw_pos - play->hw_ptr;
+
+ if (delta < 0) {
+ memset(play->area + play->hw_ptr, 0, play->size - play->hw_ptr);
+ memset(play->area, 0, hw_pos);
+ } else
+ memset(play->area + play->hw_ptr, 0, delta);
+
+ play->hw_ptr = hw_pos;
+
+ spin_unlock(&play->lock);
+ if (waitqueue_active(&audio_config->writequeue)) {
+ int avail = avail_data_len(playback, audio_config);
+
+ if (avail >= play->cfg.period_bytes)
+ wake_up_interruptible(&audio_config->writequeue);
+ }
+}
+
+bool fh_acw_dma_chan_filter(struct dma_chan *chan, void *filter_param)
+{
+ int dma_channel = *(int *)filter_param;
+ bool ret = false;
+
+ if (chan->chan_id == dma_channel)
+ {
+ ret = true;
+ }
+ return ret;
+}
+
+static int arg_config_support(struct fh_audio_cfg_arg * cfg)
+{
+ return 0;
+}
+
+static void reset_dma_buff(enum audio_type type, struct fh_audio_cfg *audio_config)
+{
+ if (capture == type)
+ {
+ audio_config->capture.appl_ptr = 0;
+ audio_config->capture.hw_ptr = 0;
+ }
+ else
+ {
+ audio_config->playback.appl_ptr = 0;
+ audio_config->playback.hw_ptr = 0;
+ }
+}
+
+unsigned int config_flag = 0;
+static long fh_audio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct fh_audio_cfg_arg cfg;
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev *dev = container_of(miscdev, struct audio_dev, fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ int pid;
+ int rx_status, tx_status;
+
+ pid = current->tgid;
+ switch (cmd)
+ {
+ case AC_INIT_CAPTURE_MEM:
+
+ if (copy_from_user((void *)&cfg, (void __user *)arg, sizeof(struct fh_audio_cfg_arg)))
+ {
+ pr_err( "copy err\n");
+ return -EIO;
+ }
+ if (0 == arg_config_support(&cfg))
+ {
+ if (down_trylock(&audio_config->sem_capture))
+ {
+ pr_err( "another thread is running capture.\n");
+ return -EBUSY;
+ }
+ infor_record.record_pid = pid;
+ audio_config->capture.cfg.io_type = cfg.io_type;
+ audio_config->capture.cfg.volume = cfg.volume;
+ audio_config->capture.cfg.rate = cfg.rate;
+ audio_config->capture.cfg.channels = cfg.channels;
+ audio_config->capture.cfg.buffer_size = cfg.buffer_size;
+ audio_config->capture.cfg.frame_bit = FIX_SAMPLE_BIT;
+ audio_config->capture.cfg.period_size = cfg.period_size;
+ audio_config->capture.cfg.buffer_bytes = frames_to_bytes(audio_config->capture.cfg.frame_bit,audio_config->capture.cfg.buffer_size);
+ audio_config->capture.cfg.period_bytes = frames_to_bytes(audio_config->capture.cfg.frame_bit,audio_config->capture.cfg.period_size);
+ audio_config->capture.cfg.start_threshold =audio_config->capture.cfg.buffer_bytes;
+ audio_config->capture.cfg.stop_threshold = audio_config->capture.cfg.buffer_bytes;
+ reset_dma_buff(capture, audio_config);
+ init_waitqueue_head(&audio_config->readqueue);
+ spin_lock_init(&audio_config->capture.lock);
+ init_audio(capture, audio_config);
+
+ /* * config wrapper work format * */
+ writel(0x55, fh_audio_module.vaddr + ACW_DAT_CTRL);//set work format
+ writel(0x111, fh_audio_module.vaddr + ACW_I2S_CTRL);//set work format
+ writel(0x00, fh_audio_module.vaddr + ACW_TRACK_CTRL);
+ config_flag = 1;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+
+ break;
+ case AC_INIT_PLAYBACK_MEM:
+ if (copy_from_user((void *)&cfg, (void __user *)arg, sizeof(struct fh_audio_cfg_arg)))
+ {
+ pr_err( "copy err\n");
+ return -EIO;
+ }
+
+ if (0 == arg_config_support(&cfg))
+ {
+ if (down_trylock(&audio_config->sem_playback))
+ {
+ pr_err( "another thread is running playback.\n");
+ return -EBUSY;
+ }
+ infor_record.play_pid = pid;
+ audio_config->playback.cfg.io_type = cfg.io_type;
+ audio_config->playback.cfg.volume = cfg.volume;
+ audio_config->playback.cfg.rate = cfg.rate;
+ audio_config->playback.cfg.channels = cfg.channels;
+ audio_config->playback.cfg.buffer_size = cfg.buffer_size;
+ audio_config->playback.cfg.frame_bit = FIX_SAMPLE_BIT;
+ audio_config->playback.cfg.period_size = cfg.period_size;
+ audio_config->playback.cfg.buffer_bytes = frames_to_bytes(audio_config->playback.cfg.frame_bit,audio_config->playback.cfg.buffer_size);
+ audio_config->playback.cfg.period_bytes = frames_to_bytes(audio_config->playback.cfg.frame_bit,audio_config->playback.cfg.period_size);
+ audio_config->playback.cfg.start_threshold =audio_config->playback.cfg.buffer_bytes;
+ audio_config->playback.cfg.stop_threshold = audio_config->playback.cfg.buffer_bytes;
+ reset_dma_buff(playback, audio_config);
+ if(!config_flag){
+ /* * config wrapper work format * */
+ writel(0x55, fh_audio_module.vaddr + ACW_DAT_CTRL);//set work format
+ writel(0x111, fh_audio_module.vaddr + ACW_I2S_CTRL);//set work format
+
+ writel(0x00, fh_audio_module.vaddr + ACW_TRACK_CTRL); //select left channel
+ /** dont config again **/
+ config_flag = 1;
+
+ }
+ init_waitqueue_head(&audio_config->writequeue);
+ spin_lock_init(&audio_config->playback.lock);
+ init_audio(playback, audio_config);
+ }
+ else
+ {
+ return -EINVAL;
+ }
+ break;
+ case AC_AI_EN:
+ if (infor_record.record_pid != pid){
+ return -EBUSY;
+ }
+ return fh_acw_start_capture(audio_config);
+ case AC_AO_EN:
+ if (infor_record.play_pid != pid) {
+ return -EBUSY;
+ }
+ return fh_acw_start_playback(audio_config);
+ case AC_SET_VOL:
+ case AC_SET_INPUT_MODE:
+ case AC_SET_OUTPUT_MODE:
+ return 0;
+ case AC_AI_DISABLE:
+ pr_info("[ac_driver]AC_AI_DISABLE\n");
+ if (infor_record.record_pid != pid) {
+ return -EBUSY;
+ }
+ fh_acw_stop_capture(audio_config);
+ pr_info(" AC_AI_DISABLE\n");
+ break;
+ case AC_AO_DISABLE:
+ pr_info("[ac_driver]AC_AO_DISABLE\n");
+ if (infor_record.play_pid != pid) {
+ return -EBUSY;
+ }
+ fh_acw_stop_playback(audio_config);
+ pr_info(" AC_AO_DISABLE\n");
+ break;
+ case AC_AI_PAUSE:
+ if (infor_record.record_pid != pid) {
+ return -EBUSY;
+ }
+ pr_info( "capture pause\n");
+ audio_config->capture.state = STATE_PAUSE;
+ rx_status = readl(fh_audio_module.vaddr + ACW_RXFIFO_CTRL);/*rx fifo disable*/
+ rx_status = rx_status&(~(1<<0));
+ writel(rx_status, fh_audio_module.vaddr + ACW_RXFIFO_CTRL);/*rx fifo disable*/
+ break;
+ case AC_AI_RESUME:
+ if (infor_record.record_pid != pid) {
+ return -EBUSY;
+ }
+ pr_info( "capture resume\n");
+ audio_config->capture.state = STATE_RUN;
+#ifndef CONFIG_MACH_FH8830_FPGA
+ rx_status = readl(fh_audio_module.vaddr + ACW_RXFIFO_CTRL);//clear rx fifo
+ rx_status = rx_status|(1<<4);
+ writel(rx_status,fh_audio_module.vaddr + ACW_RXFIFO_CTRL);/*enable rx fifo*/
+ rx_status = rx_status&(~(1<<4));
+ rx_status = rx_status|(1<<0);
+ writel(rx_status,fh_audio_module.vaddr + ACW_RXFIFO_CTRL);/*enable rx fifo*/
+#endif
+ break;
+ case AC_AO_PAUSE:
+ if (infor_record.play_pid != pid) {
+ return -EBUSY;
+ }
+ audio_config->playback.state = STATE_PAUSE;
+ pr_info( "playback pause\n");
+ tx_status = readl(fh_audio_module.vaddr + ACW_TXFIFO_CTRL);/*rx fifo disable*/
+ tx_status = tx_status&(~(1<<0));
+ writel(tx_status, fh_audio_module.vaddr + ACW_TXFIFO_CTRL);/*tx fifo disable*/
+ break;
+ case AC_AO_RESUME:
+ if (infor_record.play_pid != pid) {
+ return -EBUSY;
+ }
+ pr_info( "playback resume\n");
+ audio_config->playback.state = STATE_RUN;
+ tx_status = readl(fh_audio_module.vaddr + ACW_TXFIFO_CTRL);//clear rx fifo
+ tx_status = tx_status|(1<<0);
+ writel(tx_status,fh_audio_module.vaddr + ACW_TXFIFO_CTRL); //enable tx fifo read enable
+ break;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int fh_audio_open(struct inode *ip, struct file *fp)
+{
+ u32 reg;
+
+ fp->private_data = &fh_audio_dev.fh_audio_miscdev;
+ //enable interrupts
+ reg = readl(fh_audio_module.vaddr + ACW_CTRL);
+ reg |= 0xa; //tx & rx, under & overflow
+ writel(reg, fh_audio_module.vaddr + ACW_CTRL);
+ return 0;
+}
+
+static u32 fh_audio_poll(struct file *filp, poll_table *wait)
+{
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev *dev = container_of(miscdev, struct audio_dev, fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ u32 mask = 0;
+ long avail;
+ if (STATE_RUN == audio_config->capture.state)
+ {
+ poll_wait(filp,&audio_config->readqueue,wait);
+ avail = avail_data_len(capture, audio_config);
+ if (avail > audio_config->capture.cfg.period_bytes)
+ {
+ mask |= POLLIN | POLLRDNORM;
+ }
+ }
+ if (STATE_RUN == audio_config->playback.state)
+ {
+ poll_wait(filp,&audio_config->writequeue,wait);
+ avail = avail_data_len(playback, audio_config);
+ if (avail > audio_config->playback.cfg.period_bytes)
+ {
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ }
+ return mask;
+}
+
+static int fh_audio_read(struct file *filp, char __user *buf, size_t len, loff_t *off)
+{
+
+ int ret;
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev *dev = container_of(miscdev, struct audio_dev, fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ int after,left;
+ int pid,avail;
+ pid = current->tgid;
+ if (infor_record.record_pid != pid){
+ return -EBUSY;
+ }
+
+ avail = avail_data_len(capture, audio_config);
+ if (avail > len)
+ {
+ avail = len;
+ }
+ after = avail + audio_config->capture.appl_ptr;
+ if(after > audio_config->capture.size)
+ {
+ left = avail - (audio_config->capture.size - audio_config->capture.appl_ptr);
+ ret = copy_to_user(buf, audio_config->capture.area+audio_config->capture.appl_ptr, audio_config->capture.size-audio_config->capture.appl_ptr);
+ ret = copy_to_user(buf+audio_config->capture.size-audio_config->capture.appl_ptr,audio_config->capture.area,left);
+ spin_lock(&audio_config->capture.lock);
+ audio_config->capture.appl_ptr = left;
+ spin_unlock(&audio_config->capture.lock);
+ }
+ else
+ {
+ ret = copy_to_user(buf,audio_config->capture.area+audio_config->capture.appl_ptr,avail);
+ spin_lock(&audio_config->capture.lock);
+ audio_config->capture.appl_ptr += avail;
+ spin_unlock(&audio_config->capture.lock);
+ }
+
+ return avail;
+
+}
+
+static int fh_audio_write(struct file *filp, const char __user *buf,
+ size_t len, loff_t *off)
+{
+
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev *dev = container_of(miscdev, struct audio_dev, fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ int ret;
+ int after,left;
+ int pid,avail;
+ pid = current->tgid;
+ if (infor_record.play_pid != pid){
+ return -EBUSY;
+ }
+ avail = avail_data_len(playback,audio_config);
+ if (0 == avail)
+ {
+ return 0;
+ }
+ if (avail > len)
+ {
+ avail = len;
+ }
+ after = avail+audio_config->playback.appl_ptr;
+ if(after > audio_config->playback.size)
+ {
+ left = avail - (audio_config->playback.size-audio_config->playback.appl_ptr);
+ ret = copy_from_user(audio_config->playback.area+audio_config->playback.appl_ptr,buf,audio_config->playback.size-audio_config->playback.appl_ptr);
+ ret = copy_from_user(audio_config->playback.area,buf+audio_config->playback.size-audio_config->playback.appl_ptr,left);
+ spin_lock(&audio_config->playback.lock);
+ audio_config->playback.appl_ptr = left;
+ spin_unlock(&audio_config->playback.lock);
+ }
+ else
+ {
+ ret = copy_from_user(audio_config->playback.area+audio_config->playback.appl_ptr,buf,avail);
+ spin_lock(&audio_config->playback.lock);
+ audio_config->playback.appl_ptr += avail;
+ spin_unlock(&audio_config->playback.lock);
+ }
+
+ return avail;
+}
+
+static irqreturn_t fh_audio_interrupt(int irq, void *dev_id)
+{
+ u32 interrupts, rx_status;
+ struct fh_audio_cfg *audio_config = &fh_audio_dev.audio_config;
+
+ interrupts = readl(fh_audio_module.vaddr + ACW_CTRL);
+ //interrupts &= ~(0x3ff) << 16;
+ writel(interrupts, fh_audio_module.vaddr + ACW_CTRL);
+
+ if(interrupts & ACW_INTR_RX_UNDERFLOW)
+ {
+ fh_acw_stop_capture(audio_config);
+ fh_acw_start_capture(audio_config);
+ PRINT_AUDIO_DBG("ACW_INTR_RX_UNDERFLOW\n");
+ }
+
+ if(interrupts & ACW_INTR_RX_OVERFLOW)
+ {
+ if (audio_config->capture.state == STATE_RUN) {
+ fh_acw_stop_capture(audio_config);
+ fh_acw_start_capture(audio_config);
+ } else {
+ rx_status = readl(fh_audio_module.vaddr + ACW_RXFIFO_CTRL);//clear rx fifo
+ rx_status = rx_status|(1<<4);
+ writel(rx_status,fh_audio_module.vaddr + ACW_RXFIFO_CTRL);
+ }
+ PRINT_AUDIO_DBG("ACW_INTR_RX_OVERFLOW\n");
+ }
+
+ if(interrupts & ACW_INTR_TX_UNDERFLOW)
+ {
+ fh_acw_stop_playback(audio_config);
+ fh_acw_start_playback(audio_config);
+ PRINT_AUDIO_DBG("ACW_INTR_TX_UNDERFLOW\n");
+ }
+
+ if(interrupts & ACW_INTR_TX_OVERFLOW)
+ {
+ fh_acw_stop_playback(audio_config);
+ fh_acw_start_playback(audio_config);
+ PRINT_AUDIO_DBG("ACW_INTR_TX_OVERFLOW\n");
+ }
+
+ PRINT_AUDIO_DBG("interrupts: 0x%x\n", interrupts);
+
+ return IRQ_HANDLED;
+}
+
+static const struct file_operations acw_fops =
+{
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .unlocked_ioctl = fh_audio_ioctl,
+ .release = fh_audio_close,
+ .open = fh_audio_open,
+ .poll = fh_audio_poll,
+ .read = fh_audio_read,
+ .write = fh_audio_write,
+
+};
+
+static int fh_audio_drv_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int irq;
+ int rx_dma_channel, tx_dma_channel, dma_master;
+ int dma_rx_hs_num, dma_tx_hs_num;
+ struct resource *res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+
+ fh_audio_module.vaddr = of_iomap(np, 0);
+
+ ret = of_property_read_s32(np, "rx_dma_channel", &rx_dma_channel);
+ ret |= of_property_read_s32(np, "tx_dma_channel", &tx_dma_channel);
+ ret |= of_property_read_s32(np, "dma_master", &dma_master);
+ ret |= of_property_read_s32(np, "dma_rx_hs_num", &dma_rx_hs_num);
+ ret |= of_property_read_s32(np, "dma_tx_hs_num", &dma_tx_hs_num);
+
+ if (ret) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "error when parse dmacfg %s", np->full_name);
+ goto out_return;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+
+ fh_audio_module.clk = of_clk_get_by_name(np, "ac_clk");
+
+ fh_audio_module.acodec_pclk = of_clk_get_by_name(np, "acodec_pclk");
+ fh_audio_module.acodec_mclk = of_clk_get_by_name(np, "acodec_mclk");
+
+#else
+ struct fh_i2s_platform_data *plat_data =
+ (struct fh_i2s_platform_data *)dev_get_platdata(&pdev->dev);
+
+ rx_dma_channel = plat_data->dma_capture_channel;
+ tx_dma_channel = plat_data->dma_playback_channel;
+ dma_master = plat_data->dma_master;
+ dma_rx_hs_num = plat_data->dma_rx_hs_num;
+ dma_tx_hs_num = plat_data->dma_tx_hs_num;
+
+ fh_audio_module.vaddr = devm_ioremap(&pdev->dev, res_mem->start,
+ resource_size(res_mem));
+
+ irq = irq_create_mapping(NULL, ACW_IRQ);
+
+ fh_audio_module.clk = clk_get(NULL, plat_data->clk);
+ if (plat_data->acodec_pclk)
+ fh_audio_module.acodec_pclk = clk_get(NULL, plat_data->acodec_pclk);
+ if (plat_data->acodec_mclk)
+ fh_audio_module.acodec_mclk = clk_get(NULL, plat_data->acodec_mclk);
+#endif
+
+ if (res_mem)
+ fh_audio_module.paddr = (void *)res_mem->start;
+
+
+ if (!fh_audio_module.vaddr || !fh_audio_module.paddr) {
+ ret = -ENOMEM;
+ goto out_return;
+ }
+
+
+ if (rx_dma_channel < 0 || tx_dma_channel < 0 || dma_master < 0) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "invalid dma_channel");
+ goto out_return;
+ } else if (dma_rx_hs_num < 0 || dma_tx_hs_num < 0) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "invalid dma_hs_num");
+ goto out_return;
+ } else {
+ fh_audio_dev.channel_assign.capture_channel = rx_dma_channel;
+ fh_audio_dev.channel_assign.playback_channel = tx_dma_channel;
+ fh_audio_dev.dma_master = dma_master;
+ fh_audio_dev.dma_rx_hs_num = dma_rx_hs_num;
+ fh_audio_dev.dma_tx_hs_num = dma_tx_hs_num;
+ dev_info(&pdev->dev, "rx_dma_channel %d, tx_dma_channel %d, \
+ dma_master %d", rx_dma_channel, tx_dma_channel, dma_master);
+ }
+
+ if (IS_ERR(fh_audio_module.clk)) {
+ fh_audio_module.clk = NULL;
+ dev_err(&pdev->dev, "failed to get acw clk\n");
+ } else {
+ clk_prepare_enable(fh_audio_module.clk);
+ }
+
+ if (IS_ERR(fh_audio_module.acodec_pclk))
+ fh_audio_module.acodec_pclk = NULL;
+ else
+ clk_prepare_enable(fh_audio_module.acodec_pclk);
+
+ if (IS_ERR(fh_audio_module.acodec_mclk))
+ fh_audio_module.acodec_mclk = NULL;
+ else
+ clk_prepare_enable(fh_audio_module.acodec_mclk);
+
+ spin_lock_init(&fh_audio_module.lock);
+
+ ret = misc_register(&fh_audio_dev.fh_audio_miscdev);
+
+ if (ret)
+ goto out_return;
+
+ if (irq <= 0) {
+ dev_info(&pdev->dev, "%s: ERROR: cannot get irq\n", __func__);
+ ret = -ENXIO;
+ goto out_return;
+ }
+
+ fh_audio_module.irq = irq;
+
+ ret = devm_request_irq(&pdev->dev, irq, fh_audio_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, &fh_audio_module);
+
+ if (ret)
+ goto out_return;
+
+ dev_info(&pdev->dev, "FH ACW Driver\n");
+ return 0;
+
+out_return:
+ return ret;
+}
+
+static int fh_acw_drv_remove(struct platform_device *pdev)
+{
+ misc_deregister(&fh_audio_dev.fh_audio_miscdev);
+
+ devm_free_irq(&pdev->dev, fh_audio_module.irq, &fh_audio_module);
+
+ if (fh_audio_module.clk) {
+ clk_disable_unprepare(fh_audio_module.clk);
+ clk_put(fh_audio_module.clk);
+ }
+ dev_info(&pdev->dev, "FH ACW Driver Removed\n");
+ return 0;
+}
+
+static const struct of_device_id fh_dma_of_id_table[] = {
+ { .compatible = "fh,fh-acw" },
+ {}
+};
+
+static struct platform_driver fh_audio_driver = {
+ .probe = fh_audio_drv_probe,
+ .remove = fh_acw_drv_remove,
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(fh_dma_of_id_table),
+ }
+};
+
+static int audio_prealloc_dma_buffer(struct fh_audio_cfg *audio_config)
+{
+ int pg;
+ gfp_t gfp_flags;
+ pg = get_order(AUDIO_DMA_PREALLOC_SIZE);
+ gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN;
+ audio_config->capture.dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ audio_config->capture.area = dma_alloc_coherent(&audio_config->capture.dev, PAGE_SIZE << pg, &audio_config->capture.addr, gfp_flags );
+ if (!audio_config->capture.area)
+ {
+ pr_err("no enough mem for capture buffer alloc\n");
+ return -1;
+ }
+ audio_config->playback.dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ audio_config->playback.area = dma_alloc_coherent(&audio_config->playback.dev, PAGE_SIZE << pg, &audio_config->playback.addr, gfp_flags );
+ if (!audio_config->playback.area)
+ {
+ pr_err("no enough mem for playback buffer alloc\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void audio_free_prealloc_dma_buffer(struct fh_audio_cfg *audio_config)
+{
+ int pg;
+ pg = get_order(AUDIO_DMA_PREALLOC_SIZE);
+ dma_free_coherent(&audio_config->capture.dev, PAGE_SIZE<<pg, audio_config->capture.area, audio_config->capture.addr);
+ dma_free_coherent(&audio_config->playback.dev, PAGE_SIZE<<pg, audio_config->playback.area, audio_config->playback.addr);
+}
+
+static void init_audio_mutex(struct fh_audio_cfg *audio_config)
+{
+ sema_init(&audio_config->sem_capture, 1);
+ sema_init(&audio_config->sem_playback, 1);
+}
+
+static int audio_request_dma_channel(void)
+{
+ dma_cap_mask_t mask;
+ /*request audio rx dma channel*/
+ dma_rx_transfer = kzalloc(sizeof(struct fh_audio_dma), GFP_KERNEL);
+ if (!dma_rx_transfer)
+ {
+ pr_err("alloc dma_rx_transfer failed\n");
+ goto mem_fail;
+ }
+ memset(dma_rx_transfer, 0, sizeof(struct fh_audio_dma));
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_rx_transfer->chan = dma_request_channel(mask, fh_acw_dma_chan_filter, &fh_audio_dev.channel_assign.capture_channel);
+ if (!dma_rx_transfer->chan)
+ {
+ pr_err("request audio rx dma channel failed \n");
+ goto channel_fail;
+ }
+
+ /*request audio tx dma channel*/
+ dma_tx_transfer = kzalloc(sizeof(struct fh_audio_dma), GFP_KERNEL);
+ if (!dma_tx_transfer)
+ {
+ pr_err("alloc dma_tx_transfer failed\n");
+ goto mem_fail;
+ }
+ memset(dma_tx_transfer, 0, sizeof(struct fh_audio_dma));
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_tx_transfer->chan = dma_request_channel(mask, fh_acw_dma_chan_filter, &fh_audio_dev.channel_assign.playback_channel);
+ if (!dma_tx_transfer->chan)
+ {
+ pr_err("request dma channel failed \n");
+ return -EFAULT;
+ }
+#ifdef STERO
+ /*request audio tx dma channel*/
+ dma_tx_right_transfer = kzalloc(sizeof(struct fh_audio_dma), GFP_KERNEL);
+ if (!dma_tx_right_transfer)
+ {
+ pr_err("alloc dma_tx_right_transfer failed\n");
+ goto mem_fail;
+ }
+ memset(dma_tx_right_transfer, 0, sizeof(struct fh_audio_dma));
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_tx_right_transfer->chan = dma_request_channel(mask, TX_RIGHT_CHANNEL_DMA_CHANNEL, &fh_audio_dev.channel_assign.playback_channel);
+ if (!dma_tx_right_transfer->chan)
+ {
+ pr_err("request dma channel dma_tx_right_transfer failed \n");
+ return -EFAULT;
+ }
+#endif
+ return 0;
+channel_fail:
+ if (dma_rx_transfer->chan)
+ {
+ dma_release_channel(dma_rx_transfer->chan);
+ dma_rx_transfer->chan = NULL;
+ }
+ if (dma_tx_transfer->chan)
+ {
+ dma_release_channel(dma_tx_transfer->chan);
+ dma_tx_transfer->chan = NULL;
+ }
+#ifdef STERO
+ if (dma_tx_right_transfer->chan)
+ {
+ dma_release_channel(dma_tx_right_transfer->chan);
+ dma_tx_right_transfer->chan = NULL;
+ }
+#endif
+mem_fail:
+ if (dma_rx_transfer != NULL)
+ {
+ kfree(dma_rx_transfer);
+ dma_rx_transfer = NULL;
+ }
+ if (dma_tx_transfer != NULL)
+ {
+ kfree(dma_tx_transfer);
+ dma_tx_transfer = NULL;
+ }
+#ifdef STERO
+ if (dma_tx_right_transfer != NULL)
+ {
+ kfree(dma_tx_right_transfer);
+ dma_tx_right_transfer = NULL;
+ }
+#endif
+ return -EFAULT;
+}
+
+static void audio_release_dma_channel(void)
+{
+ /*release audio tx dma channel*/
+ if (dma_tx_transfer != NULL)
+ {
+ if (dma_tx_transfer->chan) {
+ dma_release_channel(dma_tx_transfer->chan);
+ dma_tx_transfer->chan = NULL;
+ }
+ kfree(dma_tx_transfer);
+ dma_tx_transfer = NULL;
+ }
+
+ /*release audio rx dma channel*/
+ if (dma_rx_transfer != NULL)
+ {
+ if (dma_rx_transfer->chan) {
+ dma_release_channel(dma_rx_transfer->chan);
+ dma_rx_transfer->chan = NULL;
+ }
+
+ kfree(dma_rx_transfer);
+ dma_rx_transfer = NULL;
+ }
+#ifdef STERO
+ /*release audio tx dma channel*/
+ if (dma_tx_right_transfer != NULL)
+ {
+ if (dma_tx_right_transfer->chan) {
+ dma_release_channel(dma_tx_right_transfer->chan);
+ dma_tx_right_transfer->chan = NULL;
+ }
+ kfree(dma_tx_right_transfer);
+ dma_tx_right_transfer = NULL;
+ }
+
+#endif
+
+}
+
+static int __init fh_audio_init(void)
+{
+ int ret = 0;
+#ifdef CONFIG_FH_ACW_PROC
+ create_proc();
+#endif
+ init_audio_mutex(&fh_audio_dev.audio_config);
+ ret = platform_driver_register(&fh_audio_driver);
+ if (ret)
+ goto failed;
+ ret = audio_prealloc_dma_buffer(&fh_audio_dev.audio_config);
+ if (ret)
+ goto unregister_driver;
+ ret = audio_request_dma_channel();
+ if (ret)
+ goto free_dma_buffer;
+
+ return 0;
+
+free_dma_buffer:
+ audio_free_prealloc_dma_buffer(&fh_audio_dev.audio_config);
+unregister_driver:
+ platform_driver_unregister(&fh_audio_driver);
+failed:
+#ifdef CONFIG_FH_ACW_PROC
+ remove_proc();
+#endif
+ return ret;
+}
+module_init(fh_audio_init);
+
+static void __exit fh_audio_exit(void)
+{
+
+#ifdef CONFIG_FH_ACW_PROC
+ remove_proc();
+#endif
+ audio_release_dma_channel();
+ audio_free_prealloc_dma_buffer(&fh_audio_dev.audio_config);
+ platform_driver_unregister(&fh_audio_driver);
+}
+module_exit(fh_audio_exit);
+
+MODULE_AUTHOR("Fullhan");
+MODULE_DESCRIPTION("Fullhan ACW device driver");
+MODULE_LICENSE("GPL");
+
+/****************************debug proc*****************************/
+#ifdef CONFIG_FH_ACW_PROC
+#include <linux/proc_fs.h>
+
+#define PROC_NAME "driver/"DEVICE_NAME
+static struct proc_dir_entry *proc_file;
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter = 0;
+
+ if (*pos == 0)
+ return &counter;
+ else
+ {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int i;
+ u32 data;
+
+ if (fh_audio_module.vaddr == NULL)
+ seq_printf(sfile, "reg is null\n");
+ else {
+ for (i = 0; i <= 0x20; i += 4) {
+ data = readl(fh_audio_module.vaddr + i);
+ seq_printf(sfile, "0x%02x reg = 0x%x\n", i, data);
+ }
+ }
+
+ return 0;
+}
+
+static const struct seq_operations fh_acw_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &fh_acw_seq_ops);
+}
+
+static struct file_operations fh_acw_proc_ops =
+{
+ .owner = THIS_MODULE,
+ .open = proc_open,
+ .read = seq_read,
+};
+
+static void create_proc(void)
+{
+ proc_file = proc_create(PROC_NAME, 0644, NULL, &fh_acw_proc_ops);
+
+ if (proc_file == NULL)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, DEVICE_NAME);
+
+}
+
+static void remove_proc(void)
+{
+ remove_proc_entry(PROC_NAME, NULL);
+}
+#endif
diff --git a/drivers/misc/fh_clk_miscdev.c b/drivers/misc/fh_clk_miscdev.c
new file mode 100644
index 00000000..1407422c
--- /dev/null
+++ b/drivers/misc/fh_clk_miscdev.c
@@ -0,0 +1,174 @@
+#include <linux/miscdevice.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/printk.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/fh_clk_miscdev.h>
+
+/* #define FH_CLK_DEBUG */
+
+#if defined(FH_CLK_DEBUG)
+#define PRINT_CLK_DBG(fmt, args...) \
+ do { \
+ printk(KERN_INFO "FH_CLK_DEBUG: "); \
+ printk(KERN_INFO fmt, ##args); \
+ } while (0)
+#else
+#define PRINT_CLK_DBG(fmt, args...)
+#endif
+
+static int fh_clk_miscdev_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_clk_miscdev_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static long fh_clk_miscdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret = -ENODEV;
+ struct clk *clk;
+ struct clk_usr uclk;
+ char *local_name;
+
+ if (unlikely(_IOC_TYPE(cmd) != CLK_IOCTL_MAGIC))
+ {
+ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n",
+ __func__, _IOC_TYPE(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+
+ local_name = kmalloc(64, GFP_KERNEL);
+
+ if (unlikely(_IOC_NR(cmd) > CLK_IOCTL_MAXNR))
+ {
+ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -ENOTTY);
+ kfree(local_name);
+ return -ENOTTY;
+ }
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ {
+ ret = !access_ok(VERIFY_WRITE, (void __user *)arg,
+ _IOC_SIZE(cmd));
+ }
+ else if (_IOC_DIR(cmd) & _IOC_WRITE) {
+ ret = !access_ok(VERIFY_READ, (void __user *)arg,
+ _IOC_SIZE(cmd));
+ }
+
+ if (ret) {
+ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -EACCES);
+ kfree(local_name);
+ return -EACCES;
+ }
+
+ if (copy_from_user((void *)&uclk, (void __user *)arg,
+ sizeof(struct clk_usr))) {
+ kfree(local_name);
+ return -EFAULT;
+
+ }
+
+ if (copy_from_user((void *)local_name, (void __user *)uclk.name, 64)) {
+ kfree(local_name);
+ return -EFAULT;
+ }
+ switch(cmd)
+ {
+ case ENABLE_CLK:
+ clk = clk_get(NULL, local_name);
+ if (!IS_ERR(clk)) {
+ clk_prepare_enable(clk);
+ ret = 0;
+ }
+ break;
+ case DISABLE_CLK:
+ clk = clk_get(NULL, local_name);
+ if (!IS_ERR(clk)) {
+ clk_disable_unprepare(clk);
+ ret = 0;
+ }
+ break;
+ case SET_CLK_RATE:
+ clk = clk_get(NULL, local_name);
+ ret = PTR_ERR(clk);
+ if (!IS_ERR(clk))
+ ret = clk_set_rate(clk, uclk.frequency);
+
+ PRINT_CLK_DBG("%s, set clk: %s, rate: %lu\n",
+ __func__, local_name, uclk.frequency);
+ break;
+ case GET_CLK_RATE:
+ clk = clk_get(NULL, local_name);
+ ret = PTR_ERR(clk);
+ if (!IS_ERR(clk)) {
+ uclk.frequency = clk_get_rate(clk);
+ ret = 0;
+ }
+ PRINT_CLK_DBG("%s, get clk: %s, rate: %lu\n",__func__,
+ local_name, uclk.frequency);
+ if (copy_to_user((void __user *)arg, (void *)&uclk,
+ sizeof(struct clk_usr))){
+ kfree(local_name);
+ return -EFAULT;
+ }
+ }
+
+ kfree(local_name);
+ return ret;
+}
+
+static const struct file_operations fh_clk_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_clk_miscdev_open,
+ .release = fh_clk_miscdev_release,
+ .unlocked_ioctl = fh_clk_miscdev_ioctl,
+};
+
+static struct miscdevice fh_clk_miscdev =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_NAME,
+ .fops = &fh_clk_fops,
+};
+
+int __init fh_clk_miscdev_init(void)
+{
+ int err;
+
+ err = misc_register(&fh_clk_miscdev);
+
+ if(err < 0)
+ {
+ pr_err("%s: ERROR: %s registration failed, ret=%d",
+ __func__, DEVICE_NAME, err);
+ return -ENXIO;
+ }
+
+ pr_info("CLK misc driver init successfully\n");
+ return 0;
+}
+
+
+static void __exit fh_clk_miscdev_exit(void)
+{
+ misc_deregister(&fh_clk_miscdev);
+}
+module_init(fh_clk_miscdev_init);
+module_exit(fh_clk_miscdev_exit);
+
+MODULE_AUTHOR("QIN");
+MODULE_DESCRIPTION("Misc Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform: FH");
diff --git a/drivers/misc/fh_dma_miscdev.c b/drivers/misc/fh_dma_miscdev.c
new file mode 100644
index 00000000..78797751
--- /dev/null
+++ b/drivers/misc/fh_dma_miscdev.c
@@ -0,0 +1,308 @@
+#include <linux/miscdevice.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/printk.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+
+#include "fh_dma_miscdev.h"
+
+#ifdef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+#define NR_DESCS_PER_CHANNEL CONFIG_CHANNEL_ALLOC_DESC_NUM
+#else
+#define NR_DESCS_PER_CHANNEL 64
+#endif
+
+/* 4095 xfer * 32-bit * n desc */
+#define MEMCPY_UNIT (4095 * 4 * NR_DESCS_PER_CHANNEL)
+
+//#define FH_DMA_DEBUG
+
+#ifdef FH_DMA_DEBUG
+#define PRINT_DMA_DBG(fmt, args...) \
+ do \
+ { \
+ printk("FH_DMA_DEBUG: "); \
+ printk(fmt, ## args); \
+ } \
+ while(0)
+#else
+#define PRINT_DMA_DBG(fmt, args...) do { } while (0)
+#endif
+
+
+static void fh_dma_callback(void *data)
+{
+ PRINT_DMA_DBG("dma transfer done, end=%lu\n", jiffies);
+ complete(data);
+}
+
+static int kick_off_dma(struct dma_chan *channel, unsigned int src_offset, unsigned int dst_offset, unsigned int size)
+{
+ int ret;
+ struct completion cmp;
+ struct dma_async_tx_descriptor *dma_tx_desc = NULL;
+ struct dma_device *dma_dev = channel->device;
+ dma_cookie_t cookie;
+ unsigned long timeout;
+ unsigned long flag;
+
+ flag = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+
+ PRINT_DMA_DBG("try to copy 0x%x bytes: 0x%x --> 0x%x\n", size, src_offset, dst_offset);
+
+ dma_tx_desc = dma_dev->device_prep_dma_memcpy(channel, dst_offset, src_offset, size, flag);
+
+ PRINT_DMA_DBG("device_prep_dma_memcpy end\n");
+
+ if(!dma_tx_desc)
+ {
+ pr_err("ERROR: %s, device_prep_dma_memcpy fail\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+
+ init_completion(&cmp);
+ dma_tx_desc->callback = fh_dma_callback;
+ dma_tx_desc->callback_param = &cmp;
+ PRINT_DMA_DBG("tx_submit start\n");
+ cookie = dma_tx_desc->tx_submit(dma_tx_desc);
+ PRINT_DMA_DBG("tx_submit end\n");
+ if (dma_submit_error(cookie))
+ {
+ pr_err("ERROR: %s, tx_submit fail\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ PRINT_DMA_DBG("dma_async_issue_pending start\n");
+ dma_async_issue_pending(channel);
+ PRINT_DMA_DBG("dma_async_issue_pending end, %d\n", DMA_MEMCPY_TIMEOUT);
+
+ timeout = wait_for_completion_timeout(&cmp, msecs_to_jiffies(DMA_MEMCPY_TIMEOUT));
+
+ PRINT_DMA_DBG("wait_for_completion_timeout end, timeout: %lu\n", timeout);
+
+ if(!timeout)
+ {
+ pr_err("ERROR: %s, dma transfer fail, timeout\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+
+ ret = dma_async_is_tx_complete(channel, cookie, NULL, NULL);
+
+ if(ret)
+ {
+ pr_err("ERROR: %s, dma transfer fail, incorrect status: %d\n", __func__, ret);
+ ret = -ENODEV;
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int fh_dma_start_transfer(struct dma_chan *channel, struct dma_memcpy* memcpy)
+{
+ int ret;
+ unsigned int i;
+
+ for(i=0; i<memcpy->size / MEMCPY_UNIT; i++)
+ {
+ ret = kick_off_dma(channel, memcpy->src_addr_phy + MEMCPY_UNIT*i, memcpy->dst_addr_phy + MEMCPY_UNIT*i, MEMCPY_UNIT);
+ if(ret)
+ {
+ return ret;
+ }
+ }
+
+ ret = kick_off_dma(channel, memcpy->src_addr_phy + MEMCPY_UNIT*i, memcpy->dst_addr_phy + MEMCPY_UNIT*i, memcpy->size % MEMCPY_UNIT);
+ return ret;
+}
+
+
+static bool chan_filter(struct dma_chan *chan, void *param)
+{
+ struct dma_memcpy* memcpy = param;
+ PRINT_DMA_DBG("chan_filter, channel id: %d\n", memcpy->chan_id);
+ if(memcpy->chan_id < 0)
+ {
+ return false;
+ }
+
+ if(memcpy->chan_id == chan->chan_id)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+}
+
+static int fh_dma_memcpy(struct dma_memcpy* memcpy)
+{
+ //fixme: ioctl should be atomic, otherwise channel will be changed.
+ struct dma_chan *dma_channel;
+ dma_cap_mask_t mask;
+ int ret;
+
+ PRINT_DMA_DBG("fh_dma_memcpy start\n");
+ PRINT_DMA_DBG("ioctl, memcpy->size: 0x%x\n", memcpy->size);
+
+
+ PRINT_DMA_DBG("fh_dma_request_channel start\n");
+ dma_cap_zero(mask);
+ PRINT_DMA_DBG("dma_cap_zero end\n");
+ dma_cap_set(DMA_MEMCPY, mask);
+ PRINT_DMA_DBG("dma_cap_set end\n");
+
+ dma_channel = dma_request_channel(mask, chan_filter, memcpy);
+
+ PRINT_DMA_DBG("dma_request_channel finished, channel_addr: 0x%x\n", (u32)dma_channel);
+
+ if(!dma_channel)
+ {
+ pr_err("ERROR: %s, No Channel Available, channel: %d\n", __func__, memcpy->chan_id);
+ return -EBUSY;
+ }
+ memcpy->chan_id = dma_channel->chan_id;
+ PRINT_DMA_DBG("dma channel name: %s\n", dma_chan_name(dma_channel));
+
+ ret = fh_dma_start_transfer(dma_channel, memcpy);
+
+ if(ret)
+ {
+ pr_err("ERROR: %s, DMA Xfer Failed\n", __func__);
+ }
+
+ //dma_channel->device->device_free_chan_resources(dma_channel);
+ dma_release_channel(dma_channel);
+
+ return ret;
+}
+
+static long fh_dma_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ struct dma_memcpy* memcpy;
+
+ if (arg == 0)
+ return -EINVAL;
+
+ if (unlikely(_IOC_TYPE(cmd) != DMA_IOCTL_MAGIC))
+ {
+ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n",
+ __func__, _IOC_TYPE(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+
+ if (unlikely(_IOC_NR(cmd) > DMA_IOCTL_MAXNR))
+ {
+ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ {
+ ret = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+ }
+ else if(_IOC_DIR(cmd) & _IOC_WRITE)
+ {
+ ret = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+ }
+
+ if(ret)
+ {
+ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -EACCES);
+ return -EACCES;
+ }
+
+ switch (cmd)
+ {
+ case DMA_MEMCOPY:
+ {
+ memcpy = kzalloc(sizeof(struct dma_memcpy), GFP_KERNEL);
+ if (memcpy == NULL)
+ {
+ ret = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(memcpy, (void __user *)arg, sizeof(struct dma_memcpy)))
+ {
+ ret = EINVAL;
+ kfree(memcpy);
+ break;
+ }
+ ret = fh_dma_memcpy(memcpy);
+ kfree(memcpy);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int fh_dma_open(struct inode *inode, struct file *file)
+{
+ PRINT_DMA_DBG("fh_dma_open\n");
+ return 0;
+}
+
+static int fh_dma_release(struct inode *inode, struct file *filp)
+{
+ PRINT_DMA_DBG("fh_dma_release\n");
+ return 0;
+}
+
+
+static const struct file_operations fh_dma_fops =
+{
+ .owner = THIS_MODULE,
+ .open = fh_dma_open,
+ .release = fh_dma_release,
+ .unlocked_ioctl = fh_dma_ioctl,
+};
+
+static struct miscdevice fh_dma_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_NAME,
+ .fops = &fh_dma_fops,
+};
+
+static int __init fh_dma_init(void)
+{
+ int ret;
+
+ ret = misc_register(&fh_dma_device);
+
+ if(ret < 0)
+ {
+ pr_err("%s: ERROR: %s registration failed",
+ __func__, DEVICE_NAME);
+ return -ENXIO;
+ }
+
+ return ret;
+}
+
+static void __exit fh_dma_exit(void)
+{
+ remove_proc_entry(PROC_FILE, NULL);
+ misc_deregister(&fh_dma_device);
+}
+module_init(fh_dma_init);
+module_exit(fh_dma_exit);
+
+MODULE_AUTHOR("QIN");
+MODULE_DESCRIPTION("Misc Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform: FH");
diff --git a/drivers/misc/fh_dma_miscdev.h b/drivers/misc/fh_dma_miscdev.h
new file mode 100644
index 00000000..c294c331
--- /dev/null
+++ b/drivers/misc/fh_dma_miscdev.h
@@ -0,0 +1,32 @@
+
+#ifndef FH_DMA_MISCDEV_H_
+#define FH_DMA_MISCDEV_H_
+
+#include <linux/dmaengine.h>
+
+
+#define DEVICE_NAME "fh_dma_misc"
+#define PROC_FILE "driver/dma_misc"
+
+#define DMA_IOCTL_MAGIC 'd'
+#define RESERVERD _IO(DMA_IOCTL_MAGIC, 0)
+#define REQUEST_CHANNEL _IOWR(DMA_IOCTL_MAGIC, 1, __u32)
+#define DMA_MEMCOPY _IOWR(DMA_IOCTL_MAGIC, 2, __u32)
+
+#define DMA_IOCTL_MAXNR 14
+
+#define DMA_MEMCPY_TIMEOUT 5000 //msec
+
+struct dma_memcpy
+{
+ int chan_id;
+ void *src_addr_vir;
+ void *dst_addr_vir;
+ unsigned int size;
+ unsigned int src_addr_phy;
+ unsigned int dst_addr_phy;
+};
+
+
+
+#endif /* FH_DMA_MISCDEV_H_ */
diff --git a/drivers/misc/fh_dw_i2s.c b/drivers/misc/fh_dw_i2s.c
new file mode 100644
index 00000000..d62704e3
--- /dev/null
+++ b/drivers/misc/fh_dw_i2s.c
@@ -0,0 +1,1542 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/irqreturn.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/poll.h>
+#include <linux/ioctl.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fh_dmac.h>
+#include <mach/pmu.h>
+
+#ifdef CONFIG_USE_OF
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#else
+#include <linux/irqdomain.h>
+#endif
+#include <mach/fh_i2s_plat.h>
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/fh_acw.h>
+
+#define DEVICE_NAME "fh_audio"
+
+#define NR_DESCS_PER_CHANNEL 64
+
+#define AUDIO_DMA_PREALLOC_SIZE (CONFIG_AUDIO_DMA_BUFFER_KB * 1024)
+
+#define I2S_INTR_RX_AVAILABLE 0x1
+#define I2S_INTR_RX_OVERRUN 0x2
+#define I2S_INTR_TX_AVAILABLE 0x10
+#define I2S_INTR_TX_OVERRUN 0x20
+
+#define I2S_REG_IER_OFFSET 0x00 /*i2s enable reg*/
+#define I2S_REG_IRER_OFFSET 0x04 /*i2s receiver block enable*/
+#define I2S_REG_ITER_OFFSET 0x08 /*i2s transmitter block*/
+#define I2S_REG_CER_OFFSET 0x0c /*clk en*/
+#define I2S_REG_CCR_OFFSET 0x10 /*clk cfg reg*/
+#define I2S_REG_RXFFR_OFFSET 0x14 /*reset rx fifo reg*/
+#define I2S_REG_TXFFR_OFFSET 0x18 /*reset tx fifo reg*/
+#define I2S_REG_LRBR0_OFFSET 0x20 /*left rx/tx buf reg*/
+#define I2S_REG_RRBR0_OFFSET 0x24 /*right rx/tx buf reg*/
+#define I2S_REG_RER0_OFFSET 0x28 /*rx en register*/
+#define I2S_REG_TER0_OFFSET 0x2c /*tx en*/
+#define I2S_REG_RCR0_OFFSET 0x30 /*rx config*/
+#define I2S_REG_TCR0_OFFSET 0x34 /*tx config*/
+#define I2S_REG_ISR0_OFFSET 0x38 /*intt status reg*/
+#define I2S_REG_IMR0_OFFSET 0x3c /*intt mask reg*/
+#define I2S_REG_ROR0_OFFSET 0x40 /*rx overrun reg*/
+#define I2S_REG_TOR0_OFFSET 0x44 /*tx overrun reg*/
+#define I2S_REG_RFCR0_OFFSET 0x48 /*rx fifo config reg*/
+#define I2S_REG_TFCR0_OFFSET 0x4c /*tx fifo config reg*/
+#define I2S_REG_RFF0_OFFSET 0x50 /*rx fifo flush reg*/
+#define I2S_REG_TFF0_OFFSET 0x54 /*tx fifo flush reg*/
+
+#define I2S_REG_RXDMA_OFFSET 0x1c0 /*Receiver Block DMA Register*/
+#define I2S_REG_RRXDMA_OFFSET 0x1c4 /*Reset Receiver Block DMA Register*/
+#define I2S_REG_TXDMA_OFFSET 0x1c8 /*Transmitter Block DMA Register*/
+#define I2S_REG_RTXDMA_OFFSET 0x1cc /*Reset Transmitter Block DMA Register*/
+
+#define I2S_REG_DMACR_OFFSET 0x180 /* DMA Control Register */
+#define I2S_REG_DMATDLR_OFFSET 0x184
+#define I2S_REG_DMARDLR_OFFSET 0x188
+
+#define I2S_DMA_RXEN_BIT 0
+#define I2S_DMA_TXEN_BIT 1
+
+#define FREQ_12_288_MHz 12288000
+#define FREQ_11_2896_MHz 11289600
+/* actually pllvco_freq = freq * 4 */
+#define PLLVCO_MUL 4
+
+/* #define FH_AUDIO_DEBUG*/
+#ifdef FH_AUDIO_DEBUG
+#define PRINT_AUDIO_DBG(fmt, args...) \
+ do { \
+ pr_info(fmt, ## args); \
+ } while (0);
+#else
+#define PRINT_AUDIO_DBG(fmt, args...) do { } while (0)
+#endif
+
+static const struct file_operations fh_i2s_fops;
+
+static struct audio_dev fh_audio_dev = {
+ .channel_assign = {
+ .capture_channel = -1,
+ .playback_channel = -1,
+ },
+ .dma_master = 0,
+ .fh_audio_miscdev = {
+ .fops = &fh_i2s_fops,
+ .name = DEVICE_NAME,
+ .minor = MISC_DYNAMIC_MINOR,
+ }
+};
+
+static struct {
+ spinlock_t lock;
+ unsigned long paddr;
+ void __iomem *vaddr;
+ void __iomem *acw_vaddr;
+ struct clk *clk;
+ struct clk *pclk;
+ struct clk *acodec_pclk;
+ struct clk *acodec_mclk;
+ int irq;
+ u64 pts64;
+} fh_i2s_module;
+
+static struct infor_record_t infor_record;
+
+static struct fh_audio_dma *dma_rx_transfer;
+static struct fh_audio_dma *dma_tx_transfer;
+
+static u32 g_ac_mclk_rate;
+
+static void fh_i2s_tx_dma_done(void *arg);
+static void fh_i2s_rx_dma_done(void *arg);
+static bool fh_i2s_dma_chan_filter(struct dma_chan *chan, void *filter_param);
+static int config_i2s_clk(u32 rate, u32 bit);
+static int get_capure_data(struct fh_audio_cfg *audio_config,
+ char __user *buf, size_t len);
+
+static void fh_i2s_stop_playback(struct fh_audio_cfg *audio_config)
+{
+ if (audio_config->playback.state == STATE_STOP)
+ goto out;
+ if (audio_config->playback.state == STATE_INIT)
+ goto free;
+ audio_config->playback.state = STATE_STOP;
+ fh_dma_cyclic_stop(dma_tx_transfer->chan);
+ fh_dma_cyclic_free(dma_tx_transfer->chan);
+ __clear_bit(I2S_DMA_TXEN_BIT,
+ fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET);
+ writel(0, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET);
+
+ PRINT_AUDIO_DBG("stop play, process:%s(%d)\n",
+ current->comm, current->pid);
+
+free:
+ up(&audio_config->sem_playback);
+out:
+ return;
+}
+
+static void fh_i2s_stop_capture(struct fh_audio_cfg *audio_config)
+{
+ if (audio_config->capture.state == STATE_STOP)
+ goto out;
+ if (audio_config->capture.state == STATE_INIT)
+ goto free;
+ audio_config->capture.state = STATE_STOP;
+
+ fh_dma_cyclic_stop(dma_rx_transfer->chan);
+ fh_dma_cyclic_free(dma_rx_transfer->chan);
+
+ __clear_bit(I2S_DMA_RXEN_BIT,
+ fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET);
+ writel(0, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET);
+
+ PRINT_AUDIO_DBG("stop capture, process:%s(%d)\n",
+ current->comm, current->pid);
+
+free:
+ up(&audio_config->sem_capture);
+out:
+ return;
+}
+
+static inline long bytes_to_frames(int frame_bit, int bytes)
+{
+ return bytes * 8 / frame_bit;
+}
+
+static inline long frames_to_bytes(int frame_bit, int frames)
+{
+ return frames * frame_bit / 8;
+}
+
+static void reset_dma_buff(struct audio_ptr_t *config)
+{
+ config->appl_ptr = 0;
+ config->hw_ptr = 0;
+}
+
+static int config_i2s_frame_bit(int bit)
+{
+ int wss = 0;
+ int wlen = 0;
+
+ switch (bit) {
+ case 16:
+ wss = 0;
+ wlen = 0b010;
+ break;
+ case 24:
+ wss = 1;
+ wlen = 0b100;
+ break;
+ case 32:
+ wss = 2;
+ wlen = 0b101;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ /* config sclk cycles (ws_out) */
+ writel(wss << 3, fh_i2s_module.vaddr + I2S_REG_CCR_OFFSET);
+
+ writel(wlen, fh_i2s_module.vaddr + I2S_REG_RCR0_OFFSET);
+ writel(wlen, fh_i2s_module.vaddr + I2S_REG_TCR0_OFFSET);
+ return 0;
+}
+
+static int init_audio(enum audio_type type, struct fh_audio_cfg *audio_config,
+ struct fh_audio_cfg_arg *cfg)
+{
+ struct audio_ptr_t *config = NULL;
+ int ret = 0;
+ int pid = current->tgid;
+
+ PRINT_AUDIO_DBG("init %s, process:%s(%d)\n",
+ type == capture ? "capture" : "playback", current->comm, pid);
+
+ if (type == capture) {
+ config = &audio_config->capture;
+ init_waitqueue_head(&audio_config->readqueue);
+ } else if (type == playback) {
+ config = &audio_config->playback;
+ init_waitqueue_head(&audio_config->writequeue);
+ }
+
+ config->cfg.io_type = cfg->io_type;
+ config->cfg.volume = cfg->volume;
+ config->cfg.rate = cfg->rate;
+ config->cfg.channels = cfg->channels;
+ config->cfg.buffer_size = cfg->buffer_size;
+ config->cfg.frame_bit = cfg->frame_bit;
+ config->cfg.period_size = cfg->period_size;
+ config->cfg.buffer_bytes =
+ frames_to_bytes(config->cfg.frame_bit, config->cfg.buffer_size);
+ config->cfg.period_bytes =
+ frames_to_bytes(config->cfg.frame_bit, config->cfg.period_size);
+ config->cfg.start_threshold = config->cfg.buffer_bytes;
+ config->cfg.stop_threshold = config->cfg.buffer_bytes;
+ reset_dma_buff(config);
+ spin_lock_init(&config->lock);
+
+ ret = config_i2s_clk(cfg->rate, cfg->frame_bit);
+ if (ret) {
+ pr_err("config_i2s_clk error %d\n", ret);
+ return ret;
+ }
+
+ /* * config wrapper work format * */
+ writel(1, fh_i2s_module.vaddr + I2S_REG_RER0_OFFSET);/*rx en*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_TER0_OFFSET);/*tx en*/
+
+ /*set dma fifo size*/
+ writel(0x1f, fh_i2s_module.vaddr + I2S_REG_DMARDLR_OFFSET);
+ /*set dma fifo size*/
+ writel(0x1f, fh_i2s_module.vaddr + I2S_REG_DMATDLR_OFFSET);
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_CER_OFFSET);/*en clk*/
+
+ if (type == capture) {
+ infor_record.record_pid = pid;
+ audio_config->capture.state = STATE_INIT;
+ } else if (type == playback) {
+ infor_record.play_pid = pid;
+ audio_config->playback.state = STATE_INIT;
+ }
+
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_IER_OFFSET);
+
+ return 0;
+}
+
+static int avail_data_len(enum audio_type type, struct fh_audio_cfg *stream)
+{
+ int delta;
+
+ if (capture == type) {
+ spin_lock(&stream->capture.lock);
+ delta = stream->capture.hw_ptr - stream->capture.appl_ptr;
+ spin_unlock(&stream->capture.lock);
+ if (delta < 0)
+ delta += stream->capture.size;
+ return delta;
+ } else {
+ spin_lock(&stream->playback.lock);
+ delta = stream->playback.appl_ptr - stream->playback.hw_ptr;
+ spin_unlock(&stream->playback.lock);
+ if (delta <= 0)
+ delta += stream->playback.size;
+ return stream->playback.size - delta;
+ }
+}
+
+static int fh_audio_close(struct inode *ip, struct file *fp)
+{
+ struct miscdevice *miscdev = fp->private_data;
+ struct audio_dev
+ *dev = container_of(miscdev, struct audio_dev, fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ int pid;
+
+ pid = current->tgid;
+ if (infor_record.play_pid == pid)
+ fh_i2s_stop_playback(audio_config);
+
+ if (infor_record.record_pid == pid)
+ fh_i2s_stop_capture(audio_config);
+ return 0;
+}
+
+static int register_tx_dma(struct fh_audio_cfg *audio_config)
+{
+ int ret;
+ struct fh_dma_slave *tx_config;
+ int dma_hs_num = fh_audio_dev.dma_tx_hs_num;
+
+ tx_config = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL);
+ if (!tx_config)
+ return -ENOMEM;
+#ifdef CONFIG_FH_DMAC
+ tx_config->cfg_hi = FHC_CFGH_DST_PER(dma_hs_num);
+#else
+ tx_config->cfg_hi = dma_hs_num;
+#endif
+ tx_config->dst_msize = FH_DMA_MSIZE_8;
+ tx_config->src_msize = FH_DMA_MSIZE_8;
+ if (audio_config->playback.cfg.frame_bit == 16)
+ tx_config->reg_width = FH_DMA_SLAVE_WIDTH_16BIT;
+ else
+ tx_config->reg_width = FH_DMA_SLAVE_WIDTH_32BIT;
+ tx_config->fc = FH_DMA_FC_D_M2P;
+ tx_config->tx_reg = (u32)fh_i2s_module.paddr + I2S_REG_TXDMA_OFFSET;
+ tx_config->src_master = 0;
+ tx_config->dst_master = fh_audio_dev.dma_master;
+
+ dma_tx_transfer->chan->private = tx_config;
+ if ((audio_config->playback.cfg.buffer_bytes
+ < audio_config->playback.cfg.period_bytes)
+ || (audio_config->playback.cfg.buffer_bytes <= 0)
+ || (audio_config->playback.cfg.period_bytes <= 0)
+ || (audio_config->playback.cfg.buffer_bytes
+ / audio_config->playback.cfg.period_bytes
+ > NR_DESCS_PER_CHANNEL)) {
+ pr_err("buffer_size and period_size are invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ dma_tx_transfer->cdesc = fh_dma_cyclic_prep(dma_tx_transfer->chan,
+ audio_config->playback.addr,
+ audio_config->playback.cfg.buffer_bytes,
+ audio_config->playback.cfg.period_bytes,
+ DMA_MEM_TO_DEV);
+ if (IS_ERR(dma_tx_transfer->cdesc)) {
+ pr_err("cyclic desc err %ld\n",
+ PTR_ERR(dma_tx_transfer->cdesc));
+ ret = -ENOMEM;
+ goto fail;
+ }
+ dma_tx_transfer->cdesc->period_callback = fh_i2s_tx_dma_done;
+ dma_tx_transfer->cdesc->period_callback_param = audio_config;
+ fh_dma_cyclic_start(dma_tx_transfer->chan);
+ kfree(tx_config);
+ /*must set NULL to tell DMA driver that we free the DMA slave*/
+ dma_tx_transfer->chan->private = NULL;
+ return 0;
+fail:
+ kfree(tx_config);
+ return ret;
+}
+
+static int register_rx_dma(struct fh_audio_cfg *audio_config)
+{
+ int ret;
+ struct fh_dma_slave *rx_config;
+ int dma_hs_num = fh_audio_dev.dma_rx_hs_num;
+
+ rx_config = kzalloc(sizeof(struct fh_dma_slave), GFP_KERNEL);
+ if (!rx_config)
+ return -ENOMEM;
+
+#ifdef CONFIG_FH_DMAC
+ rx_config->cfg_hi = FHC_CFGH_SRC_PER(dma_hs_num);
+#else
+ rx_config->cfg_hi = dma_hs_num;
+#endif
+
+ rx_config->dst_msize = FH_DMA_MSIZE_8;
+ rx_config->src_msize = FH_DMA_MSIZE_8;
+ if (audio_config->capture.cfg.frame_bit == 16)
+ rx_config->reg_width = FH_DMA_SLAVE_WIDTH_16BIT;
+ else
+ rx_config->reg_width = FH_DMA_SLAVE_WIDTH_32BIT;
+ rx_config->fc = FH_DMA_FC_D_P2M;
+ rx_config->rx_reg = (u32)fh_i2s_module.paddr + I2S_REG_RXDMA_OFFSET;
+ rx_config->src_master = fh_audio_dev.dma_master;
+ rx_config->dst_master = 0;
+ dma_rx_transfer->chan->private = rx_config;
+ if ((audio_config->capture.cfg.buffer_bytes
+ < audio_config->capture.cfg.period_bytes)
+ || (audio_config->capture.cfg.buffer_bytes <= 0)
+ || (audio_config->capture.cfg.period_bytes <= 0)
+ || (audio_config->capture.cfg.buffer_bytes
+ / audio_config->capture.cfg.period_bytes
+ > NR_DESCS_PER_CHANNEL)) {
+ pr_err("buffer_size and period_size are invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ dma_rx_transfer->cdesc = fh_dma_cyclic_prep(dma_rx_transfer->chan,
+ audio_config->capture.addr,
+ audio_config->capture.cfg.buffer_bytes,
+ audio_config->capture.cfg.period_bytes,
+ DMA_DEV_TO_MEM);
+ if (IS_ERR(dma_rx_transfer->cdesc)) {
+ pr_err("cyclic desc err %ld\n", PTR_ERR(dma_rx_transfer->cdesc));
+ ret = -ENOMEM;
+ goto fail;
+ }
+ dma_rx_transfer->cdesc->period_callback = fh_i2s_rx_dma_done;
+ dma_rx_transfer->cdesc->period_callback_param = audio_config;
+ fh_dma_cyclic_start(dma_rx_transfer->chan);
+
+ kfree(rx_config);
+ /*must set NULL to tell DMA driver that we free the DMA slave*/
+ dma_rx_transfer->chan->private = NULL;
+ return 0;
+fail:
+ kfree(rx_config);
+ return ret;
+}
+
+static int fh_i2s_start_playback(struct fh_audio_cfg *audio_config)
+{
+ int ret;
+
+ if (audio_config->playback.state == STATE_RUN)
+ return 0;
+
+ if (audio_config->playback.cfg.buffer_bytes
+ > AUDIO_DMA_PREALLOC_SIZE) {
+ pr_err("DMA prealloc buffer is smaller than"
+ "audio_config->buffer_bytes\n");
+ return -ENOMEM;
+ }
+ memset(audio_config->playback.area, 0,
+ audio_config->playback.cfg.buffer_bytes);
+ audio_config->playback.size = audio_config->playback.cfg.buffer_bytes;
+ audio_config->playback.state = STATE_RUN;
+ ret = register_tx_dma(audio_config);
+ if (ret)
+ return ret;
+
+ /*reset tx dma*/
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_RTXDMA_OFFSET);
+ /*reset tx fifo*/
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_TXFFR_OFFSET);
+
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET);/*tx en*/
+ /*dma en tx*/
+ __set_bit(I2S_DMA_TXEN_BIT, fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET);
+
+ PRINT_AUDIO_DBG("start play, process:%s(%d)\n",
+ current->comm, current->pid);
+ return 0;
+}
+
+static int fh_i2s_start_capture(struct fh_audio_cfg *audio_config)
+{
+ int ret;
+
+ if (audio_config->capture.state == STATE_RUN)
+ return 0;
+
+ if (audio_config->capture.cfg.buffer_bytes > AUDIO_DMA_PREALLOC_SIZE) {
+ pr_err(
+ "DMA prealloc buffer is smaller than audio_config->buffer_bytes\n");
+ return -ENOMEM;
+ }
+ memset(audio_config->capture.area, 0,
+ audio_config->capture.cfg.buffer_bytes);
+ audio_config->capture.size = audio_config->capture.cfg.buffer_bytes;
+
+ audio_config->capture.state = STATE_RUN;
+
+ ret = register_rx_dma(audio_config);
+ if (ret)
+ return ret;
+
+ /*reset rx dma*/
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_RRXDMA_OFFSET);
+ /*reset rx fifo*/
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_RXFFR_OFFSET);
+
+ writel(0x1, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET);/*rx en*/
+
+ /*dma en rx*/
+ __set_bit(I2S_DMA_RXEN_BIT, fh_i2s_module.vaddr + I2S_REG_DMACR_OFFSET);
+
+ PRINT_AUDIO_DBG("start play, process:%s(%d)\n",
+ current->comm, current->pid);
+
+ return 0;
+}
+
+static void fh_i2s_rx_dma_done(void *arg)
+{
+ struct fh_audio_cfg *audio_config = (struct fh_audio_cfg *) arg;
+ struct audio_ptr_t *cap = &audio_config->capture;
+ int hw_pos = 0;
+
+ fh_i2s_module.pts64 = fh_get_pts64();
+ spin_lock(&cap->lock);
+
+ hw_pos = fh_dma_get_dst_addr(dma_rx_transfer->chan) - cap->addr;
+
+ /* align to period_bytes*/
+ hw_pos -= hw_pos % cap->cfg.period_bytes;
+
+ cap->hw_ptr = hw_pos;
+
+ spin_unlock(&cap->lock);
+ if (waitqueue_active(&audio_config->readqueue)) {
+ int avail = avail_data_len(capture, audio_config);
+
+ if (avail >= cap->cfg.period_bytes)
+ wake_up_interruptible(&audio_config->readqueue);
+ }
+}
+
+static void fh_i2s_tx_dma_done(void *arg)
+{
+ struct fh_audio_cfg *audio_config = (struct fh_audio_cfg *) arg;
+ struct audio_ptr_t *play = &audio_config->playback;
+ int hw_pos = 0;
+ int delta = 0;
+
+ spin_lock(&play->lock);
+
+ hw_pos = fh_dma_get_src_addr(dma_tx_transfer->chan) - play->addr;
+
+ /* align to period_bytes*/
+ hw_pos -= hw_pos % play->cfg.period_bytes;
+ delta = hw_pos - play->hw_ptr;
+
+ if (delta < 0) {
+ memset(play->area + play->hw_ptr, 0, play->size - play->hw_ptr);
+ memset(play->area, 0, hw_pos);
+ } else
+ memset(play->area + play->hw_ptr, 0, delta);
+
+ play->hw_ptr = hw_pos;
+
+ spin_unlock(&play->lock);
+ if (waitqueue_active(&audio_config->writequeue)) {
+ int avail = avail_data_len(playback, audio_config);
+
+ if (avail >= play->cfg.period_bytes)
+ wake_up_interruptible(&audio_config->writequeue);
+ }
+}
+
+static bool fh_i2s_dma_chan_filter(struct dma_chan *chan,
+ void *filter_param)
+{
+ int dma_channel = *(int *) filter_param;
+ bool ret = false;
+
+ if (chan->chan_id == dma_channel)
+ ret = true;
+ return ret;
+}
+
+static int arg_config_support(struct fh_audio_cfg_arg *cfg)
+{
+ return 0;
+}
+
+static int fh_audio_get_frame_ext(struct fh_audio_cfg *cfg,
+ void __user *arg)
+{
+ struct fh_audio_ai_read_frame_ext frame;
+ int len = 0;
+ int rate = cfg->capture.cfg.rate;
+ int bit = cfg->capture.cfg.frame_bit;
+
+ if (copy_from_user((void *)&frame, arg, sizeof(frame)))
+ return -EIO;
+
+ len = get_capure_data(cfg, frame.data, frame.len);
+
+ frame.len = len;
+ frame.pts = fh_i2s_module.pts64 - len * 1000000 / (rate * bit / 8 * 2);
+
+ if (copy_to_user(arg, (void *)&frame, sizeof(frame)))
+ return -EIO;
+
+ return 0;
+}
+
+static long fh_dwi2s_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct fh_audio_cfg_arg cfg;
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev *dev =
+ container_of(miscdev, struct audio_dev, fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ int ret;
+ int pid;
+
+ pid = current->tgid;
+ switch (cmd) {
+ case AC_INIT_CAPTURE_MEM:
+
+ if (copy_from_user((void *)&cfg, (void __user *)arg,
+ sizeof(struct fh_audio_cfg_arg))) {
+ pr_err("copy err\n");
+ return -EIO;
+ }
+ if (0 == arg_config_support(&cfg)) {
+ if (down_trylock(&audio_config->sem_capture)) {
+ pr_info("another thread is running capture.\n");
+ return -EBUSY;
+ }
+ ret = init_audio(capture, audio_config, &cfg);
+ if (ret) {
+ up(&audio_config->sem_capture);
+ return ret;
+ }
+ } else {
+ return -EINVAL;
+ }
+
+ break;
+ case AC_INIT_PLAYBACK_MEM:
+ if (copy_from_user((void *)&cfg, (void __user *)arg,
+ sizeof(struct fh_audio_cfg_arg))) {
+ pr_err("copy err\n");
+ return -EIO;
+ }
+
+ if (0 == arg_config_support(&cfg)) {
+ if (down_trylock(&audio_config->sem_playback)) {
+ pr_err("another thread is running playback.\n");
+ return -EBUSY;
+ }
+ ret = init_audio(playback, audio_config, &cfg);
+ if (ret) {
+ up(&audio_config->sem_playback);
+ return ret;
+ }
+ } else
+ return -EINVAL;
+ break;
+ case AC_AI_EN:
+ if (infor_record.record_pid != pid)
+ return -EBUSY;
+ return fh_i2s_start_capture(audio_config);
+ case AC_AO_EN:
+ if (infor_record.play_pid != pid)
+ return -EBUSY;
+ return fh_i2s_start_playback(audio_config);
+ case AC_SET_VOL:
+ case AC_SET_INPUT_MODE:
+ case AC_SET_OUTPUT_MODE:
+ return 0;
+ case AC_AI_DISABLE:
+ pr_info("[ac_driver]AC_AI_DISABLE\n");
+ if (infor_record.record_pid != pid)
+ return -EBUSY;
+ fh_i2s_stop_capture(audio_config);
+ pr_info(" AC_AI_DISABLE\n");
+ break;
+ case AC_AO_DISABLE:
+ pr_info("[ac_driver]AC_AO_DISABLE\n");
+ if (infor_record.play_pid != pid)
+ return -EBUSY;
+ fh_i2s_stop_playback(audio_config);
+ pr_info(" AC_AO_DISABLE\n");
+ break;
+ case AC_AI_PAUSE:
+ if (infor_record.record_pid != pid)
+ return -EBUSY;
+ pr_info("capture pause\n");
+ audio_config->capture.state = STATE_PAUSE;
+ /*enable rx*/
+ writel(0, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET);
+ /*rx en*/
+ writel(0, fh_i2s_module.vaddr + I2S_REG_RER0_OFFSET);
+ break;
+ case AC_AI_RESUME:
+ if (infor_record.record_pid != pid)
+ return -EBUSY;
+ pr_info("capture resume\n");
+ audio_config->capture.state = STATE_RUN;
+ /*enable rx*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_IRER_OFFSET);
+ /*reset rx dma*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_RRXDMA_OFFSET);
+ /*reset rx fifo*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_RXFFR_OFFSET);
+ /*rx en*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_RER0_OFFSET);
+ break;
+ case AC_AO_PAUSE:
+ if (infor_record.play_pid != pid)
+ return -EBUSY;
+ audio_config->playback.state = STATE_PAUSE;
+ writel(0, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET);
+ writel(0, fh_i2s_module.vaddr + I2S_REG_TER0_OFFSET);
+ printk(KERN_INFO "playback pause\n");
+ break;
+ case AC_AO_RESUME:
+ if (infor_record.play_pid != pid)
+ return -EBUSY;
+ pr_info("playback resume\n");
+ audio_config->playback.state = STATE_RUN;
+ /*enable tx*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_ITER_OFFSET);
+ /*reset tx dma*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_RTXDMA_OFFSET);
+ /*reset tx fifo*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_TXFFR_OFFSET);
+ /*tx en*/
+ writel(1, fh_i2s_module.vaddr + I2S_REG_TER0_OFFSET);
+ break;
+ case AC_AI_READ_FRAME_EXT:
+ if (infor_record.record_pid != pid)
+ return -EBUSY;
+ return fh_audio_get_frame_ext(audio_config, (void __user *)arg);
+ case AC_AI_SET_VOL:
+ case AC_AO_SET_VOL:
+ case AC_AI_MICIN_SET_VOL:
+ case AC_AEC_SET_CONFIG:
+ case AC_NR_SET_CONFIG:
+ case AC_NR2_SET_CONFIG:
+ case AC_AGC_SET_CONFIG:
+ case AC_WORK_MODE:
+ case AC_AO_SET_MODE:
+ case AC_USING_EXTERNAL_CODEC:
+ case AC_EXT_INTF:
+ return 0;
+
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int fh_audio_open(struct inode *ip, struct file *fp)
+{
+
+ fp->private_data = &fh_audio_dev.fh_audio_miscdev;
+ return 0;
+}
+
+static u32 fh_audio_poll(struct file *filp, poll_table *wait)
+{
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev
+ *dev = container_of(miscdev, struct audio_dev,
+ fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ u32 mask = 0;
+ long avail;
+ if (STATE_RUN == audio_config->capture.state) {
+ poll_wait(filp, &audio_config->readqueue, wait);
+ avail = avail_data_len(capture, audio_config);
+ if (avail > audio_config->capture.cfg.period_bytes)
+ mask |= POLLIN | POLLRDNORM;
+ }
+ if (STATE_RUN == audio_config->playback.state) {
+ poll_wait(filp, &audio_config->writequeue, wait);
+ avail = avail_data_len(playback, audio_config);
+ if (avail > audio_config->playback.cfg.period_bytes)
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ return mask;
+}
+
+static int get_capure_data(struct fh_audio_cfg *audio_config,
+ char __user *buf, size_t len)
+{
+ int ret;
+ int after, left, avail;
+
+ /* wait for enough data*/
+ ret = wait_event_interruptible_timeout(audio_config->readqueue,
+ avail_data_len(capture, audio_config) >=
+ audio_config->capture.cfg.period_bytes,
+ msecs_to_jiffies(5000));
+
+ len -= len % (audio_config->capture.cfg.frame_bit / 8 * 2);
+
+ avail = avail_data_len(capture, audio_config);
+ if (avail > len)
+ avail = len;
+ after = avail + audio_config->capture.appl_ptr;
+ if (after > audio_config->capture.size) {
+ left = avail - (audio_config->capture.size
+ - audio_config->capture.appl_ptr);
+ ret = copy_to_user(buf, audio_config->capture.area
+ + audio_config->capture.appl_ptr,
+ audio_config->capture.size
+ - audio_config->capture.appl_ptr);
+ ret = copy_to_user(buf+audio_config->capture.size
+ -audio_config->capture.appl_ptr,
+ audio_config->capture.area, left);
+ spin_lock(&audio_config->capture.lock);
+ audio_config->capture.appl_ptr = left;
+ spin_unlock(&audio_config->capture.lock);
+ } else {
+ ret = copy_to_user(buf,
+ audio_config->capture.area+audio_config->capture.appl_ptr,
+ avail);
+ spin_lock(&audio_config->capture.lock);
+ audio_config->capture.appl_ptr += avail;
+ spin_unlock(&audio_config->capture.lock);
+ }
+
+ return avail;
+}
+
+static int fh_audio_read(struct file *filp, char __user *buf,
+ size_t len, loff_t *off)
+{
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev *dev = container_of(miscdev, struct audio_dev,
+ fh_audio_miscdev);
+ int pid;
+
+ pid = current->tgid;
+ if (infor_record.record_pid != pid)
+ return -EBUSY;
+
+ return get_capure_data(&dev->audio_config, buf, len);
+}
+
+static int fh_audio_write(struct file *filp, const char __user *buf,
+ size_t len, loff_t *off)
+{
+ struct miscdevice *miscdev = filp->private_data;
+ struct audio_dev *dev = container_of(miscdev, struct audio_dev,
+ fh_audio_miscdev);
+ struct fh_audio_cfg *audio_config = &dev->audio_config;
+ int ret;
+ int after, left;
+ int pid, avail;
+
+ pid = current->tgid;
+ if (infor_record.play_pid != pid)
+ return -EBUSY;
+
+ /* wait for enough data*/
+ ret = wait_event_interruptible_timeout(audio_config->writequeue,
+ avail_data_len(playback, audio_config) >=
+ audio_config->playback.cfg.period_bytes,
+ msecs_to_jiffies(5000));
+
+ len -= len % (audio_config->playback.cfg.frame_bit / 8 * 2);
+
+ avail = avail_data_len(playback, audio_config);
+ if (0 == avail)
+ return 0;
+ if (avail > len)
+ avail = len;
+ after = avail+audio_config->playback.appl_ptr;
+ if (after > audio_config->playback.size) {
+ left = avail - (audio_config->playback.size-
+ audio_config->playback.appl_ptr);
+ ret = copy_from_user(audio_config->playback.area
+ + audio_config->playback.appl_ptr,
+ buf, audio_config->playback.size
+ - audio_config->playback.appl_ptr);
+ ret = copy_from_user(audio_config->playback.area,
+ buf+audio_config->playback.size
+ - audio_config->playback.appl_ptr, left);
+ spin_lock(&audio_config->playback.lock);
+ audio_config->playback.appl_ptr = left;
+ spin_unlock(&audio_config->playback.lock);
+ } else {
+ ret = copy_from_user(audio_config->playback.area
+ + audio_config->playback.appl_ptr, buf, avail);
+ spin_lock(&audio_config->playback.lock);
+ audio_config->playback.appl_ptr += avail;
+ spin_unlock(&audio_config->playback.lock);
+ }
+
+ return avail;
+}
+
+static irqreturn_t fh_audio_interrupt(int irq, void *dev_id)
+{
+ u32 interrupts;
+ struct fh_audio_cfg *audio_config = &fh_audio_dev.audio_config;
+
+ interrupts = readl(fh_i2s_module.vaddr + I2S_REG_ISR0_OFFSET);
+
+ PRINT_AUDIO_DBG("interrupts: 0x%x\n", interrupts);
+
+ if (interrupts & I2S_INTR_RX_AVAILABLE) {
+ fh_i2s_stop_capture(audio_config);
+ fh_i2s_start_capture(audio_config);
+ PRINT_AUDIO_DBG("I2S_INTR_RX_AVAILABLE\n");
+ }
+
+ if (interrupts & I2S_INTR_RX_OVERRUN) {
+ if (audio_config->capture.state == STATE_RUN) {
+ fh_i2s_stop_capture(audio_config);
+ fh_i2s_start_capture(audio_config);
+ } else {
+ /* reset rx fifo*/
+ }
+ PRINT_AUDIO_DBG("I2S_INTR_RX_OVERRUN\n");
+ }
+
+ if (interrupts & I2S_INTR_TX_AVAILABLE) {
+ fh_i2s_stop_playback(audio_config);
+ fh_i2s_start_playback(audio_config);
+ PRINT_AUDIO_DBG("I2S_INTR_TX_AVAILABLE\n");
+ }
+
+ if (interrupts & I2S_INTR_TX_OVERRUN) {
+ fh_i2s_stop_playback(audio_config);
+ fh_i2s_start_playback(audio_config);
+ PRINT_AUDIO_DBG("I2S_INTR_TX_OVERRUN\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static const struct file_operations fh_i2s_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .unlocked_ioctl = fh_dwi2s_ioctl,
+ .release = fh_audio_close,
+ .open = fh_audio_open,
+ .poll = fh_audio_poll,
+ .read = fh_audio_read,
+ .write = fh_audio_write,
+
+};
+
+static int config_pllvco_freq(u32 freq)
+{
+ void __iomem *addr = fh_i2s_module.acw_vaddr;
+ if (addr == 0) {
+ pr_err("acw_vaddr is null\n");
+ return -EFAULT;
+ }
+
+ if (freq == FREQ_12_288_MHz) {
+ /* config PLLVCO to 12.288M */
+ writel(0x03, addr + 0xac);
+ msleep(20);
+ writel(0x07, addr + 0xb0);
+ writel(0x0f, addr + 0xb4);
+ writel(0x07, addr + 0xb8);
+ writel(0x31, addr + 0xbc);
+ writel(0x26, addr + 0xc0);
+ writel(0xe9, addr + 0xc4);
+ } else if (freq == FREQ_11_2896_MHz) {
+ /* config PLLVCO to 11.2896M */
+ writel(0x03, addr + 0xac);
+ msleep(20);
+ writel(0x06, addr + 0xb0);
+ writel(0x1f, addr + 0xb4);
+ writel(0x0f, addr + 0xb8);
+ writel(0x86, addr + 0xbc);
+ writel(0xc2, addr + 0xc0);
+ writel(0x26, addr + 0xc4);
+ } else {
+ pr_err("unsupport freq %d\n", freq);
+ return -EINVAL;
+ }
+
+ writel(0x00, addr + 0x9c);
+ writel(0x21, addr + 0xc8);
+ writel(0x07, addr + 0xcc);
+ writel(0x05, addr + 0xd0);
+ writel(0x02, addr + 0x8c);
+ writel(0x10, addr + 0xa0);
+
+ return 0;
+}
+
+int fh_set_ac_mclk_rate(u32 rate)
+{
+ /* make sure rate is valid */
+ if (rate == 0)
+ return -EINVAL;
+ if (FREQ_12_288_MHz * PLLVCO_MUL % rate &&
+ FREQ_11_2896_MHz * PLLVCO_MUL % rate)
+ return -EINVAL;
+
+ pr_debug("set ac_mclk: %u\n", rate);
+ g_ac_mclk_rate = rate;
+ return 0;
+}
+EXPORT_SYMBOL(fh_set_ac_mclk_rate);
+
+u32 fh_get_ac_mclk_rate(void)
+{
+ return g_ac_mclk_rate;
+}
+EXPORT_SYMBOL(fh_get_ac_mclk_rate);
+
+static int config_i2s_clk(u32 rate, u32 bit)
+{
+ u32 ret, freq, div;
+ u32 div_mclk, div_i2s, mclk_freq;
+
+ if (rate % 8000 == 0) {
+ freq = FREQ_12_288_MHz;
+ } else if (rate % 22050 == 0) {
+ freq = FREQ_11_2896_MHz;
+ } else {
+ pr_err("unsupport rate %d\n", rate);
+ return -EINVAL;
+ }
+
+ ret = config_pllvco_freq(freq);
+ if (ret) {
+ pr_err("config_pllvco_freq err %d\n", ret);
+ return ret;
+ }
+
+ div = freq * PLLVCO_MUL / rate / bit / 2;
+ if (g_ac_mclk_rate)
+ mclk_freq = g_ac_mclk_rate;
+ else
+ mclk_freq = freq;
+ div_mclk = freq * PLLVCO_MUL / mclk_freq;
+ div_i2s = div / div_mclk;
+
+ pr_debug("mclk_freq:%d div_i2s: %d div_mclk:%d\n",
+ mclk_freq, div_i2s, div_mclk);
+ if (freq * PLLVCO_MUL % mclk_freq) {
+ pr_err("config mclk_freq %d error\n", mclk_freq);
+ return -EINVAL;
+ }
+ if (div_i2s * div_mclk != div) {
+ pr_err("clk div error %d=%d*%d\n", div, div_i2s, div_mclk);
+ return -EINVAL;
+ }
+
+ if (div % 4 != 0 || freq % (rate*bit*2) != 0) {
+ pr_err("unsupport rate %d and bit %d\n", rate, bit);
+ return -EINVAL;
+ }
+
+ pr_debug("freq %d, rate %d, bit %d, div %d\n", freq, rate, bit, div);
+
+ ret = config_i2s_frame_bit(bit);
+ if (ret) {
+ pr_err("config_i2s_frame_bit err %d\n", ret);
+ return ret;
+ }
+
+ fh_pmu_dwi2s_set_clk(div_i2s, div_mclk);
+
+ return 0;
+}
+
+static int fh_audio_drv_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int irq;
+ int rx_dma_channel, tx_dma_channel, dma_master;
+ int dma_rx_hs_num, dma_tx_hs_num;
+ void *acw_virt_addr = NULL;
+ struct resource *res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *acw_np =
+ of_find_compatible_node(NULL, NULL, "fh,fh-acw");
+
+ acw_virt_addr = of_iomap(acw_np, 0);
+
+ ret = of_property_read_s32(np, "rx_dma_channel", &rx_dma_channel);
+ ret |= of_property_read_s32(np, "tx_dma_channel", &tx_dma_channel);
+ ret |= of_property_read_s32(np, "dma_master", &dma_master);
+ ret |= of_property_read_s32(np, "dma_rx_hs_num", &dma_rx_hs_num);
+ ret |= of_property_read_s32(np, "dma_tx_hs_num", &dma_tx_hs_num);
+
+ if (ret) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "error when parse dmacfg %s", np->full_name);
+ goto out_return;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+
+ fh_i2s_module.clk = of_clk_get_by_name(np, "i2s_clk");
+ fh_i2s_module.pclk = of_clk_get_by_name(np, "i2s_pclk");
+
+ fh_i2s_module.acodec_pclk = of_clk_get_by_name(np, "acodec_pclk");
+ fh_i2s_module.acodec_mclk = of_clk_get_by_name(np, "acodec_mclk");
+#else
+ struct fh_i2s_platform_data *plat_data =
+ (struct fh_i2s_platform_data *)dev_get_platdata(&pdev->dev);
+ struct resource *res_acw = platform_get_resource(pdev,
+ IORESOURCE_MEM, 1);
+
+ if (res_acw == NULL) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "cannot find acw info\n");
+ goto out_return;
+ }
+
+ acw_virt_addr = devm_ioremap_resource(&pdev->dev, res_acw);
+
+ rx_dma_channel = plat_data->dma_capture_channel;
+ tx_dma_channel = plat_data->dma_playback_channel;
+ dma_master = plat_data->dma_master;
+ dma_rx_hs_num = plat_data->dma_rx_hs_num;
+ dma_tx_hs_num = plat_data->dma_tx_hs_num;
+
+ irq = irq_create_mapping(NULL, platform_get_irq(pdev, 0));
+
+ fh_i2s_module.clk = clk_get(NULL, plat_data->clk);
+ if (plat_data->pclk)
+ fh_i2s_module.pclk = clk_get(NULL, plat_data->pclk);
+ if (plat_data->acodec_pclk)
+ fh_i2s_module.acodec_pclk = clk_get(NULL, plat_data->acodec_pclk);
+ if (plat_data->acodec_mclk)
+ fh_i2s_module.acodec_mclk = clk_get(NULL, plat_data->acodec_mclk);
+#endif
+
+ if (res_mem)
+ fh_i2s_module.paddr = res_mem->start;
+ else
+ goto out_return;
+
+ fh_i2s_module.vaddr = devm_ioremap_resource(&pdev->dev, res_mem);
+
+ if (!fh_i2s_module.vaddr || !fh_i2s_module.paddr) {
+ ret = -ENOMEM;
+ goto out_return;
+ }
+
+ if (rx_dma_channel < 0 || tx_dma_channel < 0 || dma_master < 0) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "invalid dma_channel");
+ goto out_return;
+ } else if (dma_rx_hs_num < 0 || dma_tx_hs_num < 0) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "invalid dma_hs_num");
+ goto out_return;
+ } else {
+ fh_audio_dev.channel_assign.capture_channel = rx_dma_channel;
+ fh_audio_dev.channel_assign.playback_channel = tx_dma_channel;
+ fh_audio_dev.dma_master = dma_master;
+ fh_audio_dev.dma_rx_hs_num = dma_rx_hs_num;
+ fh_audio_dev.dma_tx_hs_num = dma_tx_hs_num;
+ dev_info(&pdev->dev, "rx_dma_channel %d, tx_dma_channel %d, "
+ "dma_master %d", rx_dma_channel, tx_dma_channel, dma_master);
+ }
+
+ spin_lock_init(&fh_i2s_module.lock);
+
+ ret = misc_register(&fh_audio_dev.fh_audio_miscdev);
+
+ if (ret)
+ goto out_return;
+
+ if (irq <= 0) {
+ dev_info(&pdev->dev, "%s: ERROR: cannot get irq\n", __func__);
+ ret = -ENXIO;
+ goto out_return;
+ }
+
+ fh_i2s_module.irq = irq;
+
+ ret = devm_request_irq(&pdev->dev, irq, fh_audio_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, &fh_i2s_module);
+
+ if (ret)
+ goto out_return;
+
+ if (!acw_virt_addr) {
+ dev_info(&pdev->dev, "cannot get acw_virt_addr\n");
+ ret = -ENOMEM;
+ goto out_free_irq;
+ }
+
+ fh_i2s_module.acw_vaddr = acw_virt_addr;
+
+ if (IS_ERR_OR_NULL(fh_i2s_module.clk)) {
+ fh_i2s_module.clk = NULL;
+ dev_err(&pdev->dev, "failed to get i2s clk\n");
+ } else
+ clk_prepare_enable(fh_i2s_module.clk);
+
+ if (IS_ERR_OR_NULL(fh_i2s_module.pclk)) {
+ fh_i2s_module.pclk = NULL;
+ dev_dbg(&pdev->dev, "failed to get i2s pclk\n");
+ } else
+ clk_prepare_enable(fh_i2s_module.pclk);
+
+ if (IS_ERR_OR_NULL(fh_i2s_module.acodec_pclk)) {
+ fh_i2s_module.acodec_pclk = NULL;
+ dev_dbg(&pdev->dev, "failed to get acodec_pclk\n");
+ } else
+ clk_prepare_enable(fh_i2s_module.acodec_pclk);
+
+ if (IS_ERR_OR_NULL(fh_i2s_module.acodec_mclk)) {
+ fh_i2s_module.acodec_mclk = NULL;
+ dev_dbg(&pdev->dev, "failed to get acodec_mclk\n");
+ } else
+ clk_prepare_enable(fh_i2s_module.acodec_mclk);
+
+ dev_info(&pdev->dev, "FH DW I2S Driver\n");
+ return 0;
+
+out_free_irq:
+ devm_free_irq(&pdev->dev, irq, &fh_i2s_module);
+out_return:
+ dev_err(&pdev->dev, "%s failed\n", __func__);
+ return ret;
+}
+
+static int fh_i2s_drv_remove(struct platform_device *pdev)
+{
+ misc_deregister(&fh_audio_dev.fh_audio_miscdev);
+
+ devm_free_irq(&pdev->dev, fh_i2s_module.irq, &fh_i2s_module);
+
+ if (fh_i2s_module.clk) {
+ clk_disable_unprepare(fh_i2s_module.clk);
+ clk_put(fh_i2s_module.clk);
+ }
+ if (fh_i2s_module.pclk) {
+ clk_disable_unprepare(fh_i2s_module.pclk);
+ clk_put(fh_i2s_module.pclk);
+ }
+ iounmap(fh_i2s_module.acw_vaddr);
+ iounmap(fh_i2s_module.vaddr);
+ dev_info(&pdev->dev, "FH DW I2S Driver Removed\n");
+ return 0;
+}
+#ifdef CONFIG_USE_OF
+static const struct of_device_id fh_dma_of_id_table[] = {
+ { .compatible = "fh,fh-dw_i2s" },
+ {}
+};
+#endif
+static struct platform_driver fh_audio_driver = {
+ .probe = fh_audio_drv_probe,
+ .remove = fh_i2s_drv_remove,
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_USE_OF
+ .of_match_table = of_match_ptr(fh_dma_of_id_table),
+#endif
+ }
+};
+
+static int audio_prealloc_dma_buffer(struct fh_audio_cfg *audio_config)
+{
+ int pg;
+ gfp_t gfp_flags;
+ pg = get_order(AUDIO_DMA_PREALLOC_SIZE);
+ gfp_flags = GFP_KERNEL | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN;
+ audio_config->capture.dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ audio_config->capture.area = dma_alloc_coherent(
+ &audio_config->capture.dev, PAGE_SIZE << pg,
+ &audio_config->capture.addr, gfp_flags);
+ if (!audio_config->capture.area) {
+ pr_err("no enough mem for capture buffer alloc\n");
+ return -1;
+ }
+ audio_config->playback.dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ audio_config->playback.area = dma_alloc_coherent(
+ &audio_config->playback.dev, PAGE_SIZE << pg,
+ &audio_config->playback.addr, gfp_flags);
+ if (!audio_config->playback.area) {
+ pr_err("no enough mem for playback buffer alloc\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void audio_free_prealloc_dma_buffer(struct fh_audio_cfg *audio_config)
+{
+ int pg;
+ pg = get_order(AUDIO_DMA_PREALLOC_SIZE);
+ dma_free_coherent(&audio_config->capture.dev, PAGE_SIZE << pg,
+ audio_config->capture.area, audio_config->capture.addr);
+ dma_free_coherent(&audio_config->playback.dev, PAGE_SIZE << pg,
+ audio_config->playback.area,
+ audio_config->playback.addr);
+}
+
+static void init_audio_mutex(struct fh_audio_cfg *audio_config)
+{
+ sema_init(&audio_config->sem_capture, 1);
+ sema_init(&audio_config->sem_playback, 1);
+}
+
+static int audio_request_dma_channel(void)
+{
+ dma_cap_mask_t mask;
+
+ dma_rx_transfer = kzalloc(sizeof(struct fh_audio_dma), GFP_KERNEL);
+ if (!dma_rx_transfer) {
+ pr_err("alloc dma_rx_transfer failed\n");
+ goto mem_fail;
+ }
+
+ dma_tx_transfer = kzalloc(sizeof(struct fh_audio_dma), GFP_KERNEL);
+ if (!dma_tx_transfer) {
+ pr_err("alloc dma_tx_transfer failed\n");
+ goto mem_fail;
+ }
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_rx_transfer->chan = dma_request_channel(mask,
+ fh_i2s_dma_chan_filter,
+ &fh_audio_dev.channel_assign.capture_channel);
+ if (!dma_rx_transfer->chan) {
+ pr_err("request audio rx dma channel failed\n");
+ goto channel_fail;
+ }
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_tx_transfer->chan = dma_request_channel(mask,
+ fh_i2s_dma_chan_filter,
+ &fh_audio_dev.channel_assign.playback_channel);
+ if (!dma_tx_transfer->chan) {
+ pr_err("request tx dma channel failed\n");
+ goto channel_fail;
+ }
+
+ return 0;
+channel_fail:
+ if (dma_rx_transfer->chan) {
+ dma_release_channel(dma_rx_transfer->chan);
+ dma_rx_transfer->chan = NULL;
+ }
+ if (dma_tx_transfer->chan) {
+ dma_release_channel(dma_tx_transfer->chan);
+ dma_tx_transfer->chan = NULL;
+ }
+
+mem_fail:
+ if (dma_rx_transfer != NULL) {
+ kfree(dma_rx_transfer);
+ dma_rx_transfer = NULL;
+ }
+ if (dma_tx_transfer != NULL) {
+ kfree(dma_tx_transfer);
+ dma_tx_transfer = NULL;
+ }
+
+ return -EFAULT;
+}
+
+static void audio_release_dma_channel(void)
+{
+ /*release audio tx dma channel*/
+ if (dma_tx_transfer != NULL) {
+ if (dma_tx_transfer->chan) {
+ dma_release_channel(dma_tx_transfer->chan);
+ dma_tx_transfer->chan = NULL;
+ }
+ kfree(dma_tx_transfer);
+ dma_tx_transfer = NULL;
+ }
+
+ /*release audio rx dma channel*/
+ if (dma_rx_transfer != NULL) {
+ if (dma_rx_transfer->chan) {
+ dma_release_channel(dma_rx_transfer->chan);
+ dma_rx_transfer->chan = NULL;
+ }
+
+ kfree(dma_rx_transfer);
+ dma_rx_transfer = NULL;
+ }
+}
+
+static int __init fh_audio_init(void)
+{
+ int ret = 0;
+#ifdef CONFIG_FH_DW_I2S_PROC
+ create_proc();
+#endif
+ init_audio_mutex(&fh_audio_dev.audio_config);
+ ret = platform_driver_register(&fh_audio_driver);
+ if (ret)
+ goto failed;
+ ret = audio_prealloc_dma_buffer(&fh_audio_dev.audio_config);
+ if (ret)
+ goto unregister_driver;
+ ret = audio_request_dma_channel();
+ if (ret)
+ goto free_dma_buffer;
+
+ return 0;
+
+free_dma_buffer:
+ audio_free_prealloc_dma_buffer(&fh_audio_dev.audio_config);
+unregister_driver:
+ platform_driver_unregister(&fh_audio_driver);
+failed:
+#ifdef CONFIG_FH_DW_I2S_PROC
+ remove_proc();
+#endif
+ pr_err("%s failed\n", __func__);
+ return ret;
+}
+module_init(fh_audio_init);
+
+static void __exit fh_audio_exit(void)
+{
+#ifdef CONFIG_FH_DW_I2S_PROC
+ remove_proc();
+#endif
+ audio_release_dma_channel();
+ audio_free_prealloc_dma_buffer(&fh_audio_dev.audio_config);
+ platform_driver_unregister(&fh_audio_driver);
+}
+module_exit(fh_audio_exit);
+
+MODULE_AUTHOR("Fullhan");
+MODULE_DESCRIPTION("Fullhan DW I2S device driver");
+MODULE_LICENSE("GPL");
+
+#ifdef CONFIG_FH_DW_I2S_PROC
+/****************************debug proc*****************************/
+#include <linux/proc_fs.h>
+
+#define PROC_NAME "driver/"DEVICE_NAME
+static struct proc_dir_entry *proc_file;
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int i;
+ u32 data;
+
+ if (fh_i2s_module.vaddr == NULL)
+ seq_printf(sfile, "reg is null\n");
+ else {
+ for (i = 0; i <= 0x20; i += 4) {
+ data = readl(fh_i2s_module.vaddr + i);
+ seq_printf(sfile, "0x%02x reg = 0x%x\n", i, data);
+ }
+ }
+
+ return 0;
+}
+
+static const struct seq_operations fh_dwi2s_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &fh_dwi2s_seq_ops);
+}
+
+static struct file_operations fh_dwi2s_proc_ops =
+{
+ .owner = THIS_MODULE,
+ .open = proc_open,
+ .read = seq_read,
+};
+
+static void create_proc(void)
+{
+ proc_file = proc_create(PROC_NAME, 0644, NULL, &fh_dwi2s_proc_ops);
+
+ if (proc_file == NULL)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, DEVICE_NAME);
+
+}
+
+static void remove_proc(void)
+{
+ remove_proc_entry(PROC_NAME, NULL);
+}
+#endif
diff --git a/drivers/misc/fh_efuse.c b/drivers/misc/fh_efuse.c
new file mode 100644
index 00000000..48f7b9af
--- /dev/null
+++ b/drivers/misc/fh_efuse.c
@@ -0,0 +1,722 @@
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include <linux/fh_efuse.h>
+#include <mach/fh_efuse_plat.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+
+#define wrap_readl(wrap, name) \
+ __raw_readl(&(((struct wrap_efuse_reg *)wrap->regs)->name))
+
+#define wrap_writel(wrap, name, val) \
+ __raw_writel((val), &(((struct wrap_efuse_reg *)wrap->regs)->name))
+
+#define wrap_readw(wrap, name) \
+ __raw_readw(&(((struct wrap_efuse_reg *)wrap->regs)->name))
+
+#define wrap_writew(wrap, name, val) \
+ __raw_writew((val), &(((struct wrap_efuse_reg *)wrap->regs)->name))
+
+#define wrap_readb(wrap, name) \
+ __raw_readb(&(((struct wrap_efuse_reg *)wrap->regs)->name))
+
+#define wrap_writeb(wrap, name, val) \
+ __raw_writeb((val), &(((struct wrap_efuse_reg *)wrap->regs)->name))
+
+#define FH_EFUSE_PLAT_DEVICE_NAME "fh_efuse"
+#define FH_EFUSE_MISC_DEVICE_NAME "fh_efuse"
+#define FH_EFUSE_MISC_DEVICE_NODE_NAME "fh_efuse_node"
+#define EFUSE_HW_BUFFER_POS (4)
+
+#if defined CONFIG_ARCH_FH8632 || defined CONFIG_ARCH_FH8626V100
+#define MATCH_KEY 0x53d485a7
+#else
+#define MATCH_KEY 0x92fc0025
+#endif
+
+#define SECURE_BOOT_ENTRY (48)
+#define SECURE_BOOT_ACTIVE_VAL (1<<0)
+#define SOC_BOOT_MODE_WITH_SECURE 0xaa5555aa
+#define SECURE_PROTECT_EFUSE_ENTRY_MAX_INDEX 16
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type
+ * that only be used in this file here
+ ***************************************************************************/
+
+struct wrap_efuse_reg {
+ u32 efuse_cmd; /*0x0*/
+ u32 efuse_config; /*0x4*/
+ u32 efuse_match_key; /*0x8*/
+ u32 efuse_timing0; /*0xc*/
+ u32 efuse_timing1; /*0x10*/
+ u32 efuse_timing2; /*0x14*/
+ u32 efuse_timing3; /*0x18*/
+ u32 efuse_timing4; /*0x1c*/
+ u32 efuse_timing5; /*0x20*/
+ u32 efuse_timing6; /*0x24*/
+ u32 efuse_dout; /*0x28*/
+ u32 efuse_status0; /*0x2c*/
+ u32 efuse_status1; /*0x30*/
+ u32 efuse_status2; /*0x34*/
+ u32 efuse_status3; /*0x38*/
+ u32 efuse_status4; /*0x3c*/
+ u32 efuse_mem_info;
+};
+
+
+
+
+enum {
+ CMD_TRANS_AESKEY = 4,
+ CMD_WFLGA_AUTO = 8,
+};
+
+struct wrap_efuse_obj s_efuse_obj = {0};
+
+#define EFUSE_MAX_ENTRY 60
+#define EFUSE_DEBUG_ENTRY_NO_MIN 60
+#define EFUSE_DEBUG_ENTRY_NO_MAX 62
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static int fh_efuse_open(struct inode *inode, struct file *file);
+static int fh_efuse_release(struct inode *inode, struct file *filp);
+static long fh_efuse_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+
+static const struct file_operations fh_efuse_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_efuse_open,
+ .release = fh_efuse_release,
+ .unlocked_ioctl = fh_efuse_ioctl,
+};
+
+static struct miscdevice fh_efuse_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = FH_EFUSE_MISC_DEVICE_NAME,
+ /*.nodename = FH_EFUSE_MISC_DEVICE_NODE_NAME,*/
+ .fops = &fh_efuse_fops,
+};
+
+static int fh_efuse_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_efuse_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+void efuse_detect_complete(struct wrap_efuse_obj *obj, int pos)
+{
+ unsigned int rdata;
+ unsigned int time = 0;
+ /*printk("efuse wait pos %x...\n",pos);*/
+ do {
+ time++;
+ rdata = wrap_readl(obj, efuse_status0);
+ if (time > 1000) {
+ printk("[efuse]:detect time out...pos: 0x%x\n", pos);
+ return;
+ }
+ udelay(10);
+ } while ((rdata&(1<<pos)) != 1<<pos);
+ /*printk("efuse wait pos done...\n",pos);*/
+ udelay(10);
+}
+
+void auto_check_efuse_pro_bits(struct wrap_efuse_obj *obj, u32 *buff)
+{
+ /*first set auto check cmd*/
+ wrap_writel(obj, efuse_cmd, CMD_WFLGA_AUTO);
+ efuse_detect_complete(obj, 8);
+ /*
+ mdelay(300);
+ read status from hw status
+ bit 1 means could be writen....
+ */
+ buff[0] = wrap_readl(obj, efuse_status1);
+ buff[1] = wrap_readl(obj, efuse_status2);
+}
+
+void open_efuse_power(struct wrap_efuse_obj *obj)
+{
+ u32 data = 0;
+
+ data = wrap_readl(obj, efuse_config);
+ data |= 1<<27;
+ wrap_writel(obj, efuse_config, data);
+}
+
+void efuse_buffer_set(struct wrap_efuse_obj *obj, unsigned int value)
+{
+ u32 data;
+ data = wrap_readl(obj, efuse_config);
+ data &= ~(1 << EFUSE_HW_BUFFER_POS);
+ data |= value << EFUSE_HW_BUFFER_POS;
+
+ wrap_writel(obj, efuse_config, data);
+}
+
+void efuse_write_key_byte(struct wrap_efuse_obj *obj, u32 entry, u8 data)
+{
+ u32 temp = 0;
+ temp = (u32)data;
+ /*0~255*/
+ temp &= ~0xffffff00;
+ temp <<= 12;
+ /*0~63*/
+ entry &= 0x3f;
+ temp |= (entry<<4) | (0x02);
+ /*
+ printk("efuse write entry: %x,data: %x\n",entry,data);
+
+ printk("efuse write data :%x\n",temp);
+ wrap_writel(obj,efuse_cmd,(data<<12) + (entry<<4) + (0x02));
+ */
+ wrap_writel(obj, efuse_cmd, temp);
+ efuse_detect_complete(obj, 2);
+}
+
+void efuse_load_usrcmd(struct wrap_efuse_obj *obj)
+{
+ wrap_writel(obj, efuse_cmd, 1);
+ efuse_detect_complete(obj, 1);
+}
+
+void refresh_efuse(struct wrap_efuse_obj *obj)
+{
+ wrap_writel(obj, efuse_cmd, CMD_WFLGA_AUTO);
+ efuse_detect_complete(obj, 8);
+ efuse_load_usrcmd(obj);
+}
+
+void efuse_check_map_para(unsigned int size, struct ex_key_map *p_key_map)
+{
+ int loop;
+ if (size > MAX_EX_KEY_MAP_SIZE) {
+ printk(KERN_ERR "%s :: size : %d > max size : %d\n",
+ __func__, size, MAX_EX_KEY_MAP_SIZE);
+ }
+ for (loop = 0; loop < size; loop++) {
+ if ((p_key_map[loop].ex_mem_entry % 4 != 0)
+ || (p_key_map[loop].crypto_key_no != loop)) {
+ printk(KERN_ERR \
+ "map[%d]:entry[0x%x]:aes key[0x%x] para error..\n",
+ loop,
+ p_key_map[loop].ex_mem_entry,
+ p_key_map[loop].crypto_key_no);
+ }
+ }
+}
+
+
+
+static int get_soc_crypto_load_mode_from_efuse(struct wrap_efuse_obj *p_efuse)
+{
+ unsigned char ret_buf;
+
+ refresh_efuse(p_efuse);
+ efuse_read_entry(p_efuse, MATCH_KEY,
+ SECURE_BOOT_ENTRY, &ret_buf, 1);
+ if (ret_buf & SECURE_BOOT_ACTIVE_VAL)
+ return SOC_BOOT_MODE_WITH_SECURE;
+ return -1;
+}
+
+/*
+ * 0 :means do not use secure boot or decrypt. all efuse could be transfered to aes
+ * others :means use secure boot mode. efuse entry 0~15 DO NOT USE
+ */
+int fh_efuse_secure_check(struct wrap_efuse_obj *obj,
+u32 start_no, u32 size, struct af_alg_usr_def *p_alg)
+{
+ int ret;
+ int i;
+ int key_map_size;
+ struct ex_key_map *p_key_map;
+
+ ret = get_soc_crypto_load_mode_from_efuse(obj);
+ if (ret != SOC_BOOT_MODE_WITH_SECURE)
+ return 0;
+
+ if (obj->open_flag & CRYPTO_EX_MEM_SWITCH_KEY) {
+ if (p_alg->mode & CRYPTO_EX_MEM_SWITCH_KEY) {
+ if (p_alg->mode & CRYPTO_EX_MEM_4_ENTRY_1_KEY) {
+ key_map_size = p_alg->adv.ex_key_para.map_size;
+ p_key_map = &p_alg->adv.ex_key_para.map[0];
+ /* check para. */
+ for (i = 0; i < key_map_size; i++, p_key_map++) {
+ if (p_key_map->ex_mem_entry <
+ SECURE_PROTECT_EFUSE_ENTRY_MAX_INDEX) {
+ pr_err("Do not use secure area\n");
+ return -1;
+ }
+ }
+ }
+ } else {
+ /*efuse 0 ~ 15 must be used*/
+ return -2;
+ }
+ } else {
+ /* efuse 0 ~ 15 must be used*/
+ return -3;
+ }
+ return 0;
+}
+
+
+void efuse_check_update_trans_flag(struct wrap_efuse_obj *obj,
+u32 start_no, u32 size, struct af_alg_usr_def *p_alg){
+
+ int i;
+ struct ex_key_map *p_key_map;
+ struct ex_key_map *old_p_key_map;
+ struct af_alg_usr_def *p_old_usr_def;
+ int key_map_size;
+
+ p_old_usr_def = &obj->old_usr_def;
+ /* first check if use cpu mode */
+ if (p_old_usr_def->mode != p_alg->mode) {
+ obj->efuse_trans_flag = EFUSE_NEED_TRANS;
+ p_old_usr_def->mode = p_alg->mode;
+ /* not return here..maybe para not the same..
+ just update below. */
+ }
+ if (obj->open_flag & CRYPTO_EX_MEM_SWITCH_KEY) {
+ if (p_alg->mode & CRYPTO_EX_MEM_SWITCH_KEY) {
+ if (p_alg->mode & CRYPTO_EX_MEM_4_ENTRY_1_KEY) {
+ key_map_size = p_alg->adv.ex_key_para.map_size;
+ p_key_map = &p_alg->adv.ex_key_para.map[0];
+ old_p_key_map = &p_old_usr_def->adv.ex_key_para.map[0];
+ efuse_check_map_para(key_map_size, p_key_map);
+ /* check map size */
+ if (key_map_size != p_old_usr_def->adv.ex_key_para.map_size) {
+ /* cpy new to old */
+ memcpy(p_old_usr_def, p_alg,
+ sizeof(struct af_alg_usr_def));
+ obj->efuse_trans_flag = EFUSE_NEED_TRANS;
+ return;
+ }
+ /* check para. */
+ for (i = 0; i < key_map_size; i++,
+ p_key_map++, old_p_key_map++) {
+ if (memcmp(p_key_map, old_p_key_map,
+ sizeof(struct ex_key_map))) {
+ /* cmp error */
+ memcpy(p_old_usr_def, p_alg,
+ sizeof(struct af_alg_usr_def));
+ obj->efuse_trans_flag = EFUSE_NEED_TRANS;
+ return;
+ }
+ }
+ }
+ } else {
+ /*chip need set the map...and usr not set */
+ key_map_size = size;
+ if (key_map_size != obj->old_size) {
+ obj->old_size = key_map_size;
+ obj->efuse_trans_flag = EFUSE_NEED_TRANS;
+ return;
+ }
+ }
+ } else {
+ key_map_size = size;
+ if (key_map_size != obj->old_size) {
+ obj->old_size = key_map_size;
+ obj->efuse_trans_flag = EFUSE_NEED_TRANS;
+ return;
+ }
+ }
+}
+
+void efuse_trans_key(struct wrap_efuse_obj *obj,
+u32 start_no, u32 size, struct af_alg_usr_def *p_alg)
+{
+ int i;
+ struct ex_key_map *p_key_map;
+ int key_map_size;
+ unsigned int temp_reg;
+
+ efuse_check_update_trans_flag(obj, start_no, size, p_alg);
+ if (obj->efuse_trans_flag != EFUSE_NEED_TRANS) {
+ /* printk("###DO NOT need to update efuse para to aes...\n"); */
+ return;
+ }
+ obj->efuse_trans_flag = 0;
+
+ if (obj->open_flag & CRYPTO_EX_MEM_SWITCH_KEY) {
+ if (p_alg->mode & CRYPTO_EX_MEM_SWITCH_KEY) {
+ if (p_alg->mode & CRYPTO_EX_MEM_4_ENTRY_1_KEY) {
+ key_map_size = p_alg->adv.ex_key_para.map_size;
+ p_key_map = &p_alg->adv.ex_key_para.map[0];
+ efuse_check_map_para(key_map_size, p_key_map);
+ for (i = 0; i < key_map_size;
+ i++, p_key_map++) {
+ refresh_efuse(obj);
+ temp_reg =
+ wrap_readl(obj, efuse_config);
+ temp_reg &= ~(0xf<<28);
+ temp_reg |=
+ (p_key_map->ex_mem_entry / 4) << 28;
+ wrap_writel(obj,
+ efuse_config, temp_reg);
+ wrap_writel(obj,
+ efuse_cmd, (i << 20) + 0x04);
+ efuse_detect_complete(obj, 4);
+ }
+ }
+ } else {
+ /*chip need set the map...and usr not set */
+ key_map_size = size;
+ for (i = 0; i < key_map_size; i++) {
+ refresh_efuse(obj);
+ temp_reg = wrap_readl(obj, efuse_config);
+ temp_reg &= ~(0xf<<28);
+ temp_reg |= i << 28;
+ wrap_writel(obj, efuse_config, temp_reg);
+ wrap_writel(obj, efuse_cmd, (i << 20) + 0x04);
+ efuse_detect_complete(obj, 4);
+ }
+ }
+ } else {
+ key_map_size = size;
+ for (i = 0; i < key_map_size; i++) {
+ refresh_efuse(obj);
+ wrap_writel(obj, efuse_cmd, (i << 20) + 0x04);
+ efuse_detect_complete(obj, 4);
+ }
+ }
+
+}
+
+static void aes_biglittle_swap(u8 *buf)
+{
+ u8 tmp, tmp1;
+
+ tmp = buf[0];
+ tmp1 = buf[1];
+ buf[0] = buf[3];
+ buf[1] = buf[2];
+ buf[2] = tmp1;
+ buf[3] = tmp;
+}
+void efuse_get_lock_status(struct wrap_efuse_obj *obj,
+struct efuse_status *status)
+{
+ status->efuse_apb_lock = (wrap_readl(obj, efuse_status0)>>20) & 0x0f;
+ status->aes_ahb_lock = (wrap_readl(obj, efuse_status0)>>24) & 0x0f;
+}
+
+void efuse_read_entry(struct wrap_efuse_obj *obj,
+u32 key, u32 start_entry, u8 *buff, u32 size)
+{
+ u32 data, i;
+
+ for (i = 0; i < size; i++) {
+ wrap_writel(obj, efuse_match_key, key);
+ wrap_writel(obj, efuse_cmd, ((start_entry + i)<<4) + 0x03);
+ efuse_detect_complete(obj, 3);
+ data = wrap_readl(obj, efuse_dout);
+ *buff++ = (u8)data;
+ }
+}
+
+unsigned char efuse_read_debug_entry(u32 entry)
+{
+ unsigned char ret;
+
+ if (entry < EFUSE_DEBUG_ENTRY_NO_MIN ||
+ entry > EFUSE_DEBUG_ENTRY_NO_MAX) {
+ pr_err("Error entry %d\n", entry);
+ return 0;
+ }
+ efuse_read_entry(&s_efuse_obj, 0, entry, &ret, 1);
+ return ret;
+}
+EXPORT_SYMBOL(efuse_read_debug_entry);
+
+long fh_efuse_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int i;
+
+ EFUSE_INFO efuse_info = {0};
+ u32 *p_dst = NULL;
+ u8 *p_dst_8 = NULL;
+ unsigned int data;
+ u32 temp_swap_data[32] = {0};
+
+ if (copy_from_user((void *) &efuse_info, (void __user *) arg,
+ sizeof(EFUSE_INFO))) {
+ return -EFAULT;
+ }
+
+ refresh_efuse(&s_efuse_obj);
+ switch (cmd) {
+ case IOCTL_EFUSE_CHECK_PRO:
+ auto_check_efuse_pro_bits(&s_efuse_obj,
+ efuse_info.status.protect_bits);
+ break;
+ case IOCTL_EFUSE_WRITE_KEY:
+ if (copy_from_user((void *) &temp_swap_data[0],
+ (void __user *) efuse_info.key_buff,
+ efuse_info.key_size)) {
+ return -EFAULT;
+ }
+
+ p_dst = &temp_swap_data[0];
+
+ for (i = 0; i < efuse_info.key_size / sizeof(u32); i++)
+ aes_biglittle_swap((u8 *) (p_dst + i));
+ p_dst_8 = (u8 *)&temp_swap_data[0];
+
+ for (i = 0; i < efuse_info.key_size; i++) {
+ efuse_write_key_byte(&s_efuse_obj,
+ efuse_info.efuse_entry_no + i, *(p_dst_8 + i));
+ }
+
+ break;
+ case IOCTL_EFUSE_CHECK_LOCK:
+
+ efuse_get_lock_status(&s_efuse_obj, &efuse_info.status);
+ break;
+ case IOCTL_EFUSE_TRANS_KEY:
+ printk(KERN_WARNING "please use efuse transkey with aes...\n");
+ break;
+ case IOCTL_EFUSE_SWITCH_CPU_KEY_MODE:
+ printk(KERN_WARNING "please use cpu key with aes...\n");
+ break;
+ case IOCTL_EFUSE_SWITCH_EFUSE_KEY_MODE:
+ printk(KERN_WARNING "please use efuse key with aes...\n");
+ break;
+ case IOCTL_EFUSE_CHECK_ERROR:
+ printk(KERN_WARNING "not support...\n");
+ break;
+ case IOCTL_EFUSE_READ_KEY:
+ /*printf("match is : %x..\n",match_key);*/
+ efuse_read_entry(&s_efuse_obj, efuse_info.status.error,
+ efuse_info.efuse_entry_no,
+ (u8 *)&temp_swap_data[0], efuse_info.key_size);
+ p_dst = (u32 *)temp_swap_data;
+ for (i = 0; i < efuse_info.key_size / sizeof(u32); i++) {
+ aes_biglittle_swap((u8 *) (p_dst + i));
+ /*printk("swap data is %x\n",*(p_dst + i));*/
+ }
+ if (copy_to_user((void __user *) (efuse_info.key_buff),
+ (void *) &temp_swap_data[0],
+ efuse_info.key_size)) {
+ return -EFAULT;
+ }
+ /*memcpy(efuse_user_info,&efuse_info,sizeof(EFUSE_INFO));*/
+ break;
+ case IOCTL_EFUSE_SET_LOCK:
+ /*parse lock data...*/
+ data = efuse_info.status.aes_ahb_lock;
+ data <<= 4;
+ data &= 0xf0;
+ efuse_info.status.efuse_apb_lock &= 0x0f;
+ data |= efuse_info.status.efuse_apb_lock;
+ efuse_write_key_byte(&s_efuse_obj, 63, (u8)data);
+ break;
+ case IOCTL_EFUSE_SET_MAP_PARA_4_TO_1:
+ printk(KERN_WARNING "not support here..\
+ pls check if chip support this func and set core para\n");
+ break;
+ case IOCTL_EFUSE_SET_MAP_PARA_1_TO_1:
+ printk(KERN_WARNING "not support func here...\n");
+ break;
+ case IOCTL_EFUSE_CLR_MAP_PARA:
+ printk(KERN_WARNING "not support here...\n");
+ break;
+
+ case IOCTL_EFUSE_WRITE_ENTRY:
+ if (copy_from_user((void *) &temp_swap_data[0],
+ (void __user *) efuse_info.key_buff,
+ efuse_info.key_size)) {
+ return -EFAULT;
+ }
+ p_dst_8 = (u8 *)&temp_swap_data[0];
+ for (i = 0; i < efuse_info.key_size; i++) {
+ efuse_write_key_byte(&s_efuse_obj,
+ efuse_info.efuse_entry_no + i, *(p_dst_8 + i));
+ }
+
+ break;
+
+ case IOCTL_EFUSE_READ_ENTRY:
+ efuse_read_entry(&s_efuse_obj, efuse_info.status.error,
+ efuse_info.efuse_entry_no,
+ (u8 *)&temp_swap_data[0], efuse_info.key_size);
+ if (copy_to_user((void __user *) (efuse_info.key_buff),
+ (void *) &temp_swap_data[0],
+ efuse_info.key_size)) {
+ return -EFAULT;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ memcpy((void *)&s_efuse_obj.status, (void *)&efuse_info.status,
+ sizeof(struct efuse_status));
+ if (copy_to_user((void __user *) (&((EFUSE_INFO *)arg)->status),
+ (void *) &efuse_info.status,
+ sizeof(struct efuse_status))) {
+ return -EFAULT;
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ *
+ * function body
+ *
+ *
+ *****************************************************************************/
+static int fh_efuse_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int err = -ENODEV;
+ struct device_node *np = pdev->dev.of_node;
+ int temp;
+ struct fh_efuse_platform_data *p_efuse_plat;
+
+ if (np && !IS_ERR(np)) {
+ s_efuse_obj.open_flag = CRYPTO_CPU_SET_KEY |
+ CRYPTO_EX_MEM_SET_KEY;
+ s_efuse_obj.regs = of_iomap(np, 0);
+ if (!s_efuse_obj.regs) {
+ dev_err(&pdev->dev, "efuse io map error..\n");
+ return -EINVAL;
+ }
+ if (strcmp("enable",
+ of_get_property(np, "key_switch", &temp)) == 0)
+ s_efuse_obj.open_flag |=
+ CRYPTO_EX_MEM_SWITCH_KEY | CRYPTO_EX_MEM_4_ENTRY_1_KEY;
+ if (strcmp("enable",
+ of_get_property(np, "indep_power", &temp)) == 0)
+ s_efuse_obj.open_flag |=
+ CRYPTO_EX_MEM_INDEP_POWER;
+ } else {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "can't fetch device resource info\n");
+ return -EINVAL;
+ }
+
+ s_efuse_obj.regs = ioremap(res->start, resource_size(res));
+ if (s_efuse_obj.regs == NULL) {
+ dev_err(&pdev->dev, "ioremap resource error\n");
+ return -EINVAL;
+ }
+
+ p_efuse_plat =
+ (struct fh_efuse_platform_data *) pdev->dev.platform_data;
+ if (p_efuse_plat == NULL) {
+ dev_err(&pdev->dev, "efuse get platform data error..\n");
+ return -ENODEV;
+ }
+ s_efuse_obj.open_flag = p_efuse_plat->efuse_support_flag;
+ }
+
+
+ s_efuse_obj.clk = clk_get(&pdev->dev, "efuse_clk");
+
+ if (IS_ERR(s_efuse_obj.clk)) {
+ err = PTR_ERR(s_efuse_obj.clk);
+ return err;
+ }
+ clk_prepare_enable(s_efuse_obj.clk);
+
+ pr_info("efuse open mode is %x\n", s_efuse_obj.open_flag);
+ if (s_efuse_obj.open_flag & CRYPTO_EX_MEM_INDEP_POWER) {
+ /*efuse power up*/
+ open_efuse_power(&s_efuse_obj);
+ }
+#ifdef EFUSE_BUFFER_OFF
+ efuse_buffer_set(&s_efuse_obj, 0);
+#endif
+ err = misc_register(&fh_efuse_misc);
+ if (err != 0) {
+ dev_err(&pdev->dev, "efuse register misc error\n");
+ return err;
+ }
+
+ platform_set_drvdata(pdev, &fh_efuse_misc);
+
+ return 0;
+
+}
+
+static int fh_efuse_remove(struct platform_device *pdev)
+{
+ struct miscdevice *misc;
+
+ misc = (struct miscdevice *)platform_get_drvdata(pdev);
+ misc_deregister(misc);
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id fh_efuse_of_match[] = {
+ {.compatible = "fh,fh-efuse",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_efuse_of_match);
+#endif
+
+static struct platform_driver fh_efuse_driver = {
+ .driver = {
+ .name = "fh_efuse",
+#ifdef CONFIG_OF
+ .of_match_table = fh_efuse_of_match,
+#endif
+ },
+ .probe = fh_efuse_probe,
+ .remove = fh_efuse_remove,
+};
+
+module_platform_driver(fh_efuse_driver);
+MODULE_DESCRIPTION("fullhan EFUSE device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("zhangy@fullhan.com");
+MODULE_ALIAS("platform:FH_efuse");
diff --git a/drivers/misc/fh_efuse_tee.c b/drivers/misc/fh_efuse_tee.c
new file mode 100644
index 00000000..7ebfd0f1
--- /dev/null
+++ b/drivers/misc/fh_efuse_tee.c
@@ -0,0 +1,285 @@
+/*
+ * fh_efuse.c
+ *
+ * Created on: Mar 13, 2015
+ * Author: duobao
+ */
+#define pr_fmt(fmt) "%s %d: " fmt, __func__, __LINE__
+
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include "fh_efuse.h"
+#include <mach/fh_efuse_plat.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <tee_client_api.h>
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+
+#define FH_EFUSE_PLAT_DEVICE_NAME "fh_efuse"
+#define FH_EFUSE_MISC_DEVICE_NAME "fh_efuse"
+#define FH_EFUSE_MISC_DEVICE_NODE_NAME "fh_efuse_node"
+
+#define EFUSE_MAX_ENTRY 60
+
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static int fh_efuse_open(struct inode *inode, struct file *file);
+static int fh_efuse_release(struct inode *inode, struct file *filp);
+static long fh_efuse_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+
+static const struct file_operations fh_efuse_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_efuse_open,
+ .release = fh_efuse_release,
+ .unlocked_ioctl = fh_efuse_ioctl,
+};
+
+static struct miscdevice fh_efuse_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = FH_EFUSE_MISC_DEVICE_NAME,
+ /*.nodename = FH_EFUSE_MISC_DEVICE_NODE_NAME,*/
+ .fops = &fh_efuse_fops,
+};
+
+static TEEC_UUID TA_FH_EFUSE_UUID = \
+ { 0x796ad1ff, 0x5565, 0x4141,\
+ { 0x9a, 0x1c, 0x29, 0x00, 0x20, 0xaa, 0x9f, 0x16} };
+
+static TEEC_Context ctx;
+static TEEC_Session sess;
+
+static int fh_efuse_open(struct inode *inode, struct file *file)
+{
+ if (tee_open_session(&ctx, &sess, &TA_FH_EFUSE_UUID))
+ return -ENOENT;
+
+ return 0;
+}
+
+static int fh_efuse_release(struct inode *inode, struct file *filp)
+{
+ if (tee_close_session(&ctx, &sess))
+ return -EFAULT;
+
+ return 0;
+}
+
+#ifdef CONFIG_CRYPTO_DEV_FH_AES
+#warning efuse funcs cannot be used in aes, please use FH_AES driver for tee!!!
+struct wrap_efuse_obj s_efuse_obj = {0};
+
+void efuse_trans_key(struct wrap_efuse_obj *obj, u32 start_no,
+u32 size, struct af_alg_usr_def *p_alg)
+{
+ pr_err("not supported, must use FH_AES driver for tee!!!");
+}
+#endif
+
+static void aes_biglittle_swap(u8 *buf)
+{
+ u8 tmp, tmp1;
+
+ tmp = buf[0];
+ tmp1 = buf[1];
+ buf[0] = buf[3];
+ buf[1] = buf[2];
+ buf[2] = tmp1;
+ buf[3] = tmp;
+}
+
+long fh_efuse_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ void *key_buff = NULL;
+ EFUSE_INFO efuse_info = {0};
+ EFUSE_INFO *efuse_user_info = (EFUSE_INFO *)arg;
+ u32 temp_swap_data[32] = {0};
+ int paramTypes = 0;
+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+ int i;
+
+ memset(params, 0, sizeof(params));
+
+ if (!efuse_user_info) {
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&efuse_info, efuse_user_info, sizeof(EFUSE_INFO))) {
+ return -EFAULT;
+ }
+
+ switch (cmd) {
+ case IOCTL_EFUSE_WRITE_KEY:
+ case IOCTL_EFUSE_READ_KEY:
+ case IOCTL_EFUSE_WRITE_ENTRY:
+ case IOCTL_EFUSE_READ_ENTRY:
+ if (!efuse_info.key_buff || !efuse_info.key_size)
+ return -EINVAL;
+ if (copy_from_user(temp_swap_data, efuse_info.key_buff,
+ efuse_info.key_size)) {
+ return -EFAULT;
+ }
+
+ if (cmd == IOCTL_EFUSE_WRITE_KEY) {
+ for (i = 0; i < efuse_info.key_size / 4; i++)
+ aes_biglittle_swap((u8 *) (temp_swap_data + i));
+ }
+ key_buff = (void *)temp_swap_data;
+ paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT,
+ TEEC_MEMREF_TEMP_INOUT,
+ TEEC_NONE, TEEC_NONE);
+ params[1].tmpref.buffer = key_buff;
+ params[1].tmpref.size = efuse_info.key_size;
+ break;
+ default:
+ paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, TEEC_NONE,
+ TEEC_NONE, TEEC_NONE);
+ break;
+ }
+
+ params[0].tmpref.buffer = &efuse_info;
+ params[0].tmpref.size = sizeof(efuse_info);
+
+ ret = tee_invoke_cmd(&sess, cmd, paramTypes, params);
+ if (ret)
+ return ret;
+
+ if (copy_to_user(efuse_user_info, &efuse_info, sizeof(EFUSE_INFO)))
+ return -EFAULT;
+
+ if (cmd == IOCTL_EFUSE_READ_KEY) {
+ for (i = 0; i < efuse_info.key_size / 4; i++)
+ aes_biglittle_swap((u8 *) (temp_swap_data + i));
+ }
+
+ if (key_buff && copy_to_user(efuse_info.key_buff, temp_swap_data,
+ efuse_info.key_size)) {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ *
+ *
+ * function body
+ *
+ *
+ *****************************************************************************/
+
+
+static int fh_efuse_probe(struct platform_device *pdev)
+{
+ int err = -ENODEV;
+ u32 uuid_array[11];
+ TEEC_UUID uuid;
+
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+
+ err = of_property_read_u32_array(np, "optee-uuid", uuid_array, 11);
+
+ if (err) {
+ dev_err(&pdev->dev, "error when parse optee-uuid %s", np->full_name);
+ return err;
+ } else {
+#else
+ struct fh_efuse_platform_data *plat_data =
+ (struct fh_efuse_platform_data *)dev_get_platdata(&pdev->dev);
+
+ if (!plat_data || !plat_data->optee_uuid) {
+ dev_err(&pdev->dev, "cannot get optee-uuid from plat_data");
+ } else {
+ memcpy(uuid_array, plat_data->optee_uuid, sizeof(uuid_array));
+#endif
+ uuid = get_uuid_from_array(uuid_array);
+ dev_info(&pdev->dev,
+ "efuse-uuid: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ uuid.timeLow, uuid.timeMid, uuid.timeHiAndVersion,
+ uuid.clockSeqAndNode[0], uuid.clockSeqAndNode[1],
+ uuid.clockSeqAndNode[2], uuid.clockSeqAndNode[3],
+ uuid.clockSeqAndNode[4], uuid.clockSeqAndNode[5],
+ uuid.clockSeqAndNode[6], uuid.clockSeqAndNode[7]);
+ }
+
+ TA_FH_EFUSE_UUID = uuid;
+
+
+ err = misc_register(&fh_efuse_misc);
+ if (err != 0) {
+ dev_err(&pdev->dev, "efuse register misc error\n");
+ return err;
+ }
+
+ platform_set_drvdata(pdev, &fh_efuse_misc);
+
+ return 0;
+}
+
+static int fh_efuse_remove(struct platform_device *pdev)
+{
+ struct miscdevice *misc;
+ misc = (struct miscdevice *)platform_get_drvdata(pdev);
+ misc_deregister(misc);
+ return 0;
+}
+
+
+static const struct of_device_id fh_efuse_of_match[] = {
+ {.compatible = "fh,fh-efuse",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_efuse_of_match);
+
+static struct platform_driver fh_efuse_driver = {
+ .driver = {
+ .name = "fh_efuse",
+ .of_match_table = fh_efuse_of_match,
+ },
+ .probe = fh_efuse_probe,
+ .remove = fh_efuse_remove,
+};
+
+module_platform_driver(fh_efuse_driver);
+MODULE_DESCRIPTION("fh efuse driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FULLHAN");
+MODULE_ALIAS("platform:FH_efuse");
diff --git a/drivers/misc/fh_perf_mon.c b/drivers/misc/fh_perf_mon.c
new file mode 100644
index 00000000..ba5c98aa
--- /dev/null
+++ b/drivers/misc/fh_perf_mon.c
@@ -0,0 +1,732 @@
+/*
+ * fh_sadc.c
+ *
+ * Created on: Jan 7, 2020
+ * Author: fullhan
+ */
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/irqdomain.h>
+
+#include <mach/pmu.h>
+#include <linux/sched.h>
+#include <mach/clock.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include "fh_perf_mon.h"
+
+#define AXI_PORT_MAX 5
+
+
+struct fh_perf_mon_obj_t fh_perf_mon_obj;
+struct fh_perf_param_output lastres;
+struct clk *fh_perf_clk;
+
+static int fh_perf_mon_open(struct inode *inode, struct file *file);
+static int fh_perf_mon_release(struct inode *inode, struct file *filp);
+static long fh_perf_mon_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static void ctl_monitor(int on);
+
+static const struct file_operations fh_perf_mon_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_perf_mon_open,
+ .read = NULL,
+ .release = fh_perf_mon_release,
+ .unlocked_ioctl = fh_perf_mon_ioctl,
+};
+
+static struct miscdevice fh_perf_mon_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = FH_PERF_MON_DEVNAME,
+ .fops = &fh_perf_mon_fops,
+};
+
+enum fh_perf_state_e
+{
+ FH_PERF_STOP,
+ FH_PERF_RUNING,
+} fh_perf_state;
+
+struct fh_perf_param_input last_input_param;
+struct fh_perf_data_buff fh_databuff;
+
+static void update_lastresult(void)
+{
+ int i = 0;
+ unsigned int regval = 0;
+
+ lastres.serial_cnt++;
+ // ddr_bw
+ lastres.hw_cnt = readl(REG_PERF_MONI_REG(59))&0xff;
+
+ for (i = 0; i< AXI_PORT_MAX; i++) {
+ lastres.wr_cmd_cnt[i] = readl(REG_PERF_MONI_REG(17+i));
+ lastres.rd_cmd_cnt[i] = readl(REG_PERF_MONI_REG(22+i));
+ lastres.wr_cmd_byte[i] = readl(REG_PERF_MONI_REG(27+i));
+ lastres.rd_cmd_byte[i] = readl(REG_PERF_MONI_REG(32+i));
+ lastres.wr_sum_lat[i] = readl(REG_PERF_MONI_REG(37+i));
+ lastres.rd_sum_lat[i] = readl(REG_PERF_MONI_REG(42+i));
+ lastres.wr_cmd_cnt_lat[i] = readl(REG_PERF_MONI_REG(47+i));
+ lastres.rd_cmd_cnt_lat[i] = readl(REG_PERF_MONI_REG(52+i));
+ switch(i) {
+ default:
+ break;
+ case 0:
+ lastres.wr_ot[i] = (readl(REG_PERF_MONI_REG(15))>>0)&0x3f;
+ lastres.rd_ot[i] = (readl(REG_PERF_MONI_REG(15))>>8)&0x3f;
+ break;
+ case 1:
+ lastres.wr_ot[i] = (readl(REG_PERF_MONI_REG(15))>>16)&0x3f;
+ lastres.rd_ot[i] = (readl(REG_PERF_MONI_REG(15))>>24)&0x3f;
+ break;
+ case 2:
+ lastres.wr_ot[i] = (readl(REG_PERF_MONI_REG(16))>>0)&0x3f;
+ lastres.rd_ot[i] = (readl(REG_PERF_MONI_REG(16))>>8)&0x3f;
+ break;
+ case 3:
+ lastres.wr_ot[i] = (readl(REG_PERF_MONI_REG(16))>>16)&0x3f;
+ lastres.rd_ot[i] = (readl(REG_PERF_MONI_REG(16))>>24)&0x3f;
+ break;
+ case 4:
+ regval = readl(REG_PERF_MONI_REG(15));
+ lastres.wr_ot[i] = ((regval>>6)&0x3)|((regval>>12)&(0x3<<2))|
+ ((regval>>18)&(0x3<<4));
+ regval = readl(REG_PERF_MONI_REG(16));
+ lastres.rd_ot[i] = ((regval>>6)&0x3)|((regval>>12)&(0x3<<2))|
+ ((regval>>18)&(0x3<<4));
+ break;
+
+
+ }
+ }
+
+ lastres.ddr_wr_bw = readl(REG_PERF_MONI_REG(57));
+ lastres.ddr_rd_bw = readl(REG_PERF_MONI_REG(58));
+
+
+
+
+ if (fh_databuff.addr != 0 && fh_databuff.cnt>0) {
+ u32 idx = (lastres.serial_cnt - 1 ) % fh_databuff.cnt;
+ memcpy((void *)(fh_databuff.addr+idx*sizeof(lastres)),&lastres,sizeof(lastres));
+ }
+}
+
+static irqreturn_t fh_perf_mon_isr(int irq, void *dev_id)
+{
+
+ u32 reg;
+ update_lastresult();
+ if (last_input_param.mode == FH_PERF_SINGLE) {
+ complete(&fh_perf_mon_obj.done);
+ ctl_monitor(0);
+ }
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg |= BIT(30);
+ writel(reg, REG_PERF_MONI_REG(0));
+ reg &= ~BIT(30);
+ writel(reg, REG_PERF_MONI_REG(0));
+
+
+ return IRQ_HANDLED;
+}
+static void set_fh_perf_hw_param(struct fh_perf_param_input* input);
+static void del_char(char* str, char ch)
+{
+ char *p = str;
+ char *q = str;
+ while (*q) {
+ if (*q != ch) {
+ *p++ = *q;
+ }
+ q++;
+ }
+ *p = '\0';
+}
+
+static ssize_t fh_perf_mon_proc_write(struct file *filp, const char *buf,
+ size_t len, loff_t *off)
+{
+ int i;
+ char message[64] = {0};
+ char * const delim = ",";
+ char *cur = message;
+ char *param_str[4];
+
+ len = (len > 64) ? 64 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for (i = 0; i < 3; i++) {
+ param_str[i] = strsep(&cur, delim);
+ if (!param_str[i]) {
+ pr_err("%s: ERROR: parameter[%d] is empty\n", __func__, i);
+ pr_err("[window_time], [mode], [max_databuffcnt]\n");
+ return -EINVAL;
+ } else {
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ }
+ }
+
+
+
+
+
+ last_input_param.window_time = (u32)simple_strtoul(param_str[0], NULL, 10);
+ last_input_param.mode = (u32)simple_strtoul(param_str[1], NULL, 10);
+ pr_err("last_input_param.window_timet %x\r\n",last_input_param.window_time);
+ pr_err("last_input_param.mode %x\r\n",last_input_param.mode);
+
+ //last_input_param.mode = FH_PERF_CONTINUOUS;
+ last_input_param.ddr_bw = 1;
+ for (i = 0; i < AXI_PORT_MAX; i++) {
+ last_input_param.axi_bw[i] = 1;
+ }
+ set_fh_perf_hw_param(&last_input_param);
+
+ fh_databuff.cnt = (u32)simple_strtoul(param_str[2], NULL, 10);
+ pr_err("fh_databuff.cnt %x\r\n",fh_databuff.cnt);
+ if (fh_databuff.addr != 0) {
+ kfree((void*)fh_databuff.addr);
+ fh_databuff.addr = 0;
+ }
+ if (fh_databuff.cnt !=0) {
+ fh_databuff.addr = (u32)kzalloc(sizeof(lastres)*fh_databuff.cnt,GFP_KERNEL);
+
+ } else {
+ fh_databuff.addr = (u32)NULL;
+ }
+ pr_err("fh_databuff.addr %x\r\n",fh_databuff.addr);
+ ctl_monitor(1);
+ return len;
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+ counter = 0;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static void fh_perf_printdata(struct seq_file *sfile, struct fh_perf_param_output* printres)
+{
+ int i = 0;
+
+ seq_printf(sfile, "last serial idx 0x%x\n", printres->serial_cnt);
+ seq_printf(sfile, "hw idx 0x%x\n", printres->hw_cnt);
+ seq_printf(sfile, "DDR WR BW %u (MB/s)\n", printres->ddr_wr_bw/(last_input_param.window_time*1000));
+ seq_printf(sfile, "DDR RD BW %u (MB/s) \n", printres->ddr_rd_bw/(last_input_param.window_time*1000));
+
+ seq_printf(sfile," ");
+ for(i = 0; i< AXI_PORT_MAX; i++) {
+ seq_printf(sfile, " AXI_PORT_%02d ", i);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "wr_ot ");
+ for(i = 0; i< AXI_PORT_MAX; i++) {
+ seq_printf(sfile, " %09u ", printres->wr_ot[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "rd_ot ");
+ for(i = 0; i< AXI_PORT_MAX; i++) {
+ seq_printf(sfile, " %09u ", printres->rd_ot[i]);
+ }
+ seq_printf(sfile, "\n");
+ seq_printf(sfile, "wr_cmd_cnt ");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->wr_cmd_cnt[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "rd_cmd_cnt ");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->rd_cmd_cnt[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "wr_cmd_byte ");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->wr_cmd_byte[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "rd_cmd_byte ");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->rd_cmd_byte[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "wr_cmd_bw(MB/s)");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ",
+ printres->wr_cmd_byte[i]/(last_input_param.window_time*1000));
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "rd_cmd_bw(MB/s)");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ",
+ printres->rd_cmd_byte[i]/(last_input_param.window_time*1000));
+ }
+
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "wr_sum_lat ");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->wr_sum_lat[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "rd_sum_lat ");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->rd_sum_lat[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "wr_cmd_cnt_lat");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->wr_cmd_cnt_lat[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "rd_cmd_cnt_lat");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ", printres->rd_cmd_cnt_lat[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "wr_av_lat(cycle)");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ",
+ printres->wr_cmd_cnt_lat[i] == 0 ? 0 :
+ printres->wr_sum_lat[i]/printres->wr_cmd_cnt_lat[i]);
+ }
+ seq_printf(sfile, "\n");
+
+ seq_printf(sfile, "rd_av_lat(cycle)");
+ for(i =0; i< AXI_PORT_MAX;i++) {
+ seq_printf(sfile, " %09u ",
+ printres->rd_cmd_cnt_lat[i] == 0 ? 0 :
+ printres->rd_sum_lat[i]/printres->rd_cmd_cnt_lat[i]);
+ }
+
+
+ seq_printf(sfile, "\n");
+}
+
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int i = 0;
+
+ ctl_monitor(0);
+ if (last_input_param.window_time == 0) {
+ seq_printf(sfile, "\nPlease run fh perf first!\n");
+ return 0;
+ }
+
+ msleep(last_input_param.window_time>100?last_input_param.window_time:100);
+ seq_printf(sfile, "\nLast FH Perf Monitor Status:\n");
+ seq_printf(sfile, "window time %u ms\n", last_input_param.window_time);
+
+ if (fh_databuff.addr == (u32)NULL) {
+ fh_perf_printdata(sfile,&lastres);
+ } else {
+ struct fh_perf_param_output* cur =
+ (struct fh_perf_param_output *)fh_databuff.addr;
+
+ for (i = 0; i<fh_databuff.cnt;i++){
+ fh_perf_printdata(sfile,cur);
+ cur++;
+ }
+ }
+ return 0;
+}
+
+static const struct seq_operations fh_perf_mon_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_perf_mon_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &fh_perf_mon_seq_ops);
+}
+
+static const struct file_operations fh_perf_mon_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_perf_mon_proc_open,
+ .read = seq_read,
+ .write = fh_perf_mon_proc_write,
+ .release = seq_release,
+};
+
+static int __init fh_perf_mon_probe(struct platform_device *pdev)
+{
+ int err;
+ struct resource *res;
+
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+ fh_perf_mon_obj.regs = of_iomap(np, 0);
+ fh_perf_mon_obj.irq_no = irq_of_parse_and_map(np, 0);
+
+#else
+ fh_perf_mon_obj.irq_no = irq_create_mapping(NULL,
+ platform_get_irq(pdev, 0));
+ if (fh_perf_mon_obj.irq_no < 0) {
+ dev_err(&pdev->dev, "fh perf interrupt is not available.\n");
+ return fh_perf_mon_obj.irq_no;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "fh perf no resource\n");
+ return -EBUSY;
+ }
+
+ fh_perf_mon_obj.regs = ioremap(res->start, resource_size(res));
+#endif
+ if (fh_perf_mon_obj.regs == NULL) {
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+ fh_perf_mon_obj.regs += 0x2018;
+
+ err = request_irq(fh_perf_mon_obj.irq_no, fh_perf_mon_isr, 0,
+ "fh_perf",
+ &fh_perf_mon_obj);
+
+ if (err) {
+ dev_dbg(&pdev->dev, "request_irq failed, %d\n", err);
+ err = -ENXIO;
+ goto err_irq;
+ }
+ init_completion(&fh_perf_mon_obj.done);
+ mutex_init(&fh_perf_mon_obj.perf_lock);
+
+ err = misc_register(&fh_perf_mon_misc);
+
+ if (err < 0) {
+ pr_err("%s: ERROR: %s registration failed", __func__,
+ FH_PERF_MON_MISC_DEVICE_NAME);
+ err = -ENXIO;
+ goto misc_error;
+ }
+ fh_perf_clk = clk_get(&pdev->dev, "ahb_clk");
+
+ fh_perf_mon_obj.proc_file = proc_create(FH_PERF_MON_PROC_FILE,
+ 0644, NULL, &fh_perf_mon_proc_ops);
+
+ if (!fh_perf_mon_obj.proc_file)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, "PERF");
+
+ return 0;
+
+misc_error:
+ free_irq(fh_perf_mon_obj.irq_no, &fh_perf_mon_obj);
+
+err_irq:
+ iounmap(fh_perf_mon_obj.regs);
+
+fail_no_ioremap:
+ release_mem_region(res->start, resource_size(res));
+
+ return err;
+}
+
+static int __exit fh_perf_mon_remove(struct platform_device *pdev)
+{
+
+ struct resource *res;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ misc_deregister(&fh_perf_mon_misc);
+ free_irq(fh_perf_mon_obj.irq_no, &fh_perf_mon_obj);
+ iounmap(fh_perf_mon_obj.regs);
+ release_mem_region(res->start, resource_size(res));
+ return 0;
+
+}
+
+
+static int fh_perf_mon_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_perf_mon_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static void set_fh_perf_hw_param(struct fh_perf_param_input* input)
+{
+ u32 reg;
+ int i = 0;
+ u32 rate;
+
+ // window
+ if (IS_ERR(fh_perf_clk)) {
+ rate = 200000;
+ } else {
+ rate = clk_get_rate(fh_perf_clk)/1000;
+ }
+ reg = input->window_time*rate;
+ writel(reg, REG_PERF_MONI_REG(1));
+
+ // ddr bw
+ reg = readl(REG_PERF_MONI_REG(0));
+ if (input->ddr_bw) {
+ reg |= BIT(24);
+ } else {
+ reg &= ~BIT(24);
+ }
+ // mode
+ if (input->mode == FH_PERF_SINGLE) {
+ reg &= ~BIT(28);
+ } else {
+ reg |= BIT(28);
+ }
+ writel(reg, REG_PERF_MONI_REG(0));
+
+
+ // axi addr filter
+ for (i = 0;i < AXI_PORT_MAX; i++) {
+ if (input->addr_param[i].used == 1) {
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg |= BIT((8+i));
+ writel(reg, REG_PERF_MONI_REG(0));
+ writel(input->addr_param[i].filter, REG_PERF_MONI_REG(2+i));
+ writel(input->addr_param[i].mask, REG_PERF_MONI_REG(7+i));
+ } else {
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg &= ~BIT((8+i));
+ writel(reg, REG_PERF_MONI_REG(0));
+ writel(0, REG_PERF_MONI_REG(2+i));
+ writel(0, REG_PERF_MONI_REG(7+i));
+ }
+ }
+ // axi id filter
+ for (i = 0;i < AXI_PORT_MAX; i++) {
+ if (input->id_param[i].used == 1) {
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg |= BIT((16+i));
+ writel(reg, REG_PERF_MONI_REG(0));
+ switch (i) {
+ case 0:
+ reg = readl(REG_PERF_MONI_REG(12));
+ reg &= 0xffff0000;
+ reg |= input->id_param[i].filter|(input->id_param[i].mask<<8);
+ writel(reg, REG_PERF_MONI_REG(12));
+ break;
+ case 1:
+ reg = readl(REG_PERF_MONI_REG(12));
+ reg &= 0x0000ffff;
+ reg |= (input->id_param[i].filter<<16)|(input->id_param[i].mask<<24);
+ writel(reg, REG_PERF_MONI_REG(12));
+ break;
+ case 2:
+ reg = readl(REG_PERF_MONI_REG(13));
+ reg &= 0xFFFF0000;
+ reg |= (input->id_param[i].filter<<0)|(input->id_param[i].mask<<8);
+ writel(reg, REG_PERF_MONI_REG(13));
+ break;
+ case 3:
+ reg = readl(REG_PERF_MONI_REG(13));
+ reg &= 0x0000ffff;
+ reg |= (input->id_param[i].filter<<16)|
+ (input->id_param[i].mask<<24);
+ writel(reg, REG_PERF_MONI_REG(13));
+ break;
+ case 4:
+ reg = readl(REG_PERF_MONI_REG(14));
+ reg &= 0x0000ffff;
+ reg |= (input->id_param[i].filter<<0)|
+ (input->id_param[i].mask<<8);
+ writel(reg, REG_PERF_MONI_REG(14));
+ break;
+ default:
+ break;
+ }
+ } else {
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg &= ~BIT((16+i));
+ writel(reg, REG_PERF_MONI_REG(0));
+ switch (i) {
+ case 0:
+ reg = readl(REG_PERF_MONI_REG(12));
+ reg &= 0xffff0000;
+ writel(reg, REG_PERF_MONI_REG(12));
+ break;
+ case 1:
+ reg = readl(REG_PERF_MONI_REG(12));
+ reg &= 0x0000ffff;
+ writel(reg, REG_PERF_MONI_REG(12));
+ break;
+ case 2:
+ reg = readl(REG_PERF_MONI_REG(13));
+ reg &= 0xFFFF0000;
+ writel(reg, REG_PERF_MONI_REG(13));
+ break;
+ case 3:
+ reg = readl(REG_PERF_MONI_REG(13));
+ reg &= 0x0000ffff;
+ writel(reg, REG_PERF_MONI_REG(13));
+ break;
+ case 4:
+ reg = readl(REG_PERF_MONI_REG(14));
+ reg &= 0xffff0000;
+ writel(reg, REG_PERF_MONI_REG(14));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ // axi bw en
+ for (i = 0;i < AXI_PORT_MAX; i++) {
+ if (input->axi_bw[i] == 1) {
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg |= BIT((i));
+ writel(reg, REG_PERF_MONI_REG(0));
+ } else {
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg &= ~BIT((i));
+ writel(reg, REG_PERF_MONI_REG(0));
+ }
+ }
+
+}
+static void ctl_monitor(int on)
+{
+ u32 reg;
+ if (on) {
+ lastres.serial_cnt = 0;
+ fh_perf_state = FH_PERF_RUNING;
+ if (fh_databuff.addr != 0 && fh_databuff.cnt>0) {
+ memset((void *)fh_databuff.addr,0,sizeof(lastres)*fh_databuff.cnt);
+ }
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg |= BIT(31);
+ writel(reg, REG_PERF_MONI_REG(0));
+ } else {
+ if (FH_PERF_RUNING == fh_perf_state)
+ fh_perf_state = FH_PERF_STOP;
+ reg = readl(REG_PERF_MONI_REG(0));
+ reg &= ~BIT(31);
+ writel(reg, REG_PERF_MONI_REG(0));
+ }
+
+}
+
+
+static long fh_perf_mon_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+
+ switch(cmd) {
+ case FH_PERF_MON_START_ASYNC:
+ if (last_input_param.mode != FH_PERF_CONTINUOUS) {
+ return -EIO;
+ }
+ ctl_monitor(1);
+ break;
+ case FH_PERF_MON_STOP:
+ ctl_monitor(0);
+ break;
+ case FH_PERF_MON_SETPARAM:
+ memset(&last_input_param,0,sizeof(last_input_param));
+ ret = copy_from_user((void *)&last_input_param, (void __user *)arg, sizeof(last_input_param));
+ set_fh_perf_hw_param(&last_input_param);
+ break;
+ case FH_PERF_MON_START_SYNC:
+ if (last_input_param.mode != FH_PERF_SINGLE) {
+ return -EIO;
+ }
+ reinit_completion(&fh_perf_mon_obj.done);
+ ctl_monitor(1);
+ ret = wait_for_completion_interruptible_timeout(&fh_perf_mon_obj.done, last_input_param.window_time/10+1);
+ ret = copy_to_user( (void __user *)arg,
+ (void *)&lastres,sizeof(lastres));
+ break;
+ case FH_PERF_MON_GETLASTDATA:
+ ret = copy_to_user( (void __user *)arg,
+ (void *)&lastres,sizeof(lastres));
+ break;
+ case FH_PERF_SET_RAWDATA_BUFF:
+ ret = copy_from_user((void *)&fh_databuff,
+ (void __user *)arg, sizeof(last_input_param));
+ fh_databuff.addr =
+ (u32)ioremap(fh_databuff.addr,
+ fh_databuff.cnt*sizeof(lastres));
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static const struct of_device_id fh_perf_of_match[] = {
+ {.compatible = "fh,fh-perf",},
+ {},
+};
+
+static struct platform_driver fh_perf_mon_driver = {
+ .driver = {
+ .name = FH_PERF_MON_PLAT_DEVICE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = fh_perf_of_match,
+ },
+ .probe = fh_perf_mon_probe,
+ .remove = __exit_p(fh_perf_mon_remove),
+};
+
+
+
+
+
+static int __init fh_perf_mon_init(void)
+{
+ return platform_driver_register(&fh_perf_mon_driver);
+}
+
+static void __exit fh_perf_mon_exit(void)
+{
+
+ platform_driver_unregister(&fh_perf_mon_driver);
+
+}
+
+module_init(fh_perf_mon_init);
+module_exit(fh_perf_mon_exit);
+
+MODULE_DESCRIPTION("fh perf_mon driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("FULLHAN");
+MODULE_ALIAS("platform:FH_perf_mon");
diff --git a/drivers/misc/fh_perf_mon.h b/drivers/misc/fh_perf_mon.h
new file mode 100644
index 00000000..614a3ae3
--- /dev/null
+++ b/drivers/misc/fh_perf_mon.h
@@ -0,0 +1,110 @@
+#ifndef __FH_PERF_MON_H
+#define __FH_PERF_MON_H
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/bug.h>
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+
+#define REG_PERF_MONI_REG(id) (fh_perf_mon_obj.regs+4*(id))
+
+
+
+#define FH_PERF_MON_IOCTL_BASE 'P'
+#define FH_PERF_MON_START_ASYNC _IOWR(FH_PERF_MON_IOCTL_BASE, 0, int)
+#define FH_PERF_MON_SETPARAM _IOWR(FH_PERF_MON_IOCTL_BASE, 1, int)
+#define FH_PERF_MON_START_SYNC _IOWR(FH_PERF_MON_IOCTL_BASE, 2, int)
+#define FH_PERF_MON_GETLASTDATA _IOWR(FH_PERF_MON_IOCTL_BASE, 3, int)
+#define FH_PERF_MON_STOP _IOWR(FH_PERF_MON_IOCTL_BASE, 4, int)
+#define FH_PERF_SET_RAWDATA_BUFF _IOWR(FH_PERF_MON_IOCTL_BASE, 5, int)
+
+
+
+#define FH_PERF_MON_DEVNAME "fh_perf"
+#define FH_PERF_MON_PROC_FILE "driver/fh_perf"
+#define FH_PERF_MON_PLAT_DEVICE_NAME "fh_perf_mon"
+#define FH_PERF_MON_MISC_DEVICE_NAME "fh_perf"
+
+struct fh_perf_mon_obj_t {
+ void *regs;
+ u32 irq_no;
+ spinlock_t lock;
+ struct mutex perf_lock;
+ struct completion done;
+ struct proc_dir_entry *proc_file;
+};
+
+enum fh_perf_mode_e
+{
+ FH_PERF_SINGLE,
+ FH_PERF_CONTINUOUS,
+};
+
+struct fh_perf_adv_port_param
+{
+ u32 used;
+ u32 filter;
+ u32 mask;
+};
+
+struct fh_perf_data_buff
+{
+ u32 addr;
+ u32 cnt;
+};
+
+
+
+struct fh_perf_param_input
+{
+ enum fh_perf_mode_e mode;
+ u32 ddr_bw;
+ u32 window_time;
+ u32 axi_bw[10];
+ struct fh_perf_adv_port_param addr_param[10];
+ struct fh_perf_adv_port_param id_param[10];
+
+};
+
+struct fh_perf_param_output
+{
+ u32 serial_cnt;
+ u32 hw_cnt;
+ u32 wr_ot[10];
+ u32 rd_ot[10];
+ u32 wr_cmd_cnt[10];
+ u32 rd_cmd_cnt[10];
+ u32 wr_cmd_byte[10];
+ u32 rd_cmd_byte[10];
+ u32 wr_sum_lat[10];
+ u32 rd_sum_lat[10];
+ u32 wr_cmd_cnt_lat[10];
+ u32 rd_cmd_cnt_lat[10];
+ u32 ddr_wr_bw;
+ u32 ddr_rd_bw;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif
diff --git a/drivers/misc/fh_pinctrl_dev.c b/drivers/misc/fh_pinctrl_dev.c
new file mode 100644
index 00000000..9048ed6b
--- /dev/null
+++ b/drivers/misc/fh_pinctrl_dev.c
@@ -0,0 +1,301 @@
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <linux/printk.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <asm/uaccess.h>
+#include "fh_pinctrl_dev.h"
+
+#define FH_PINCTRL_PROC_FILE "driver/pinctrl"
+
+#undef FH_PINCTRL_DEBUG
+#ifdef FH_PINCTRL_DEBUG
+#define PRINT_DBG(fmt,args...) printk(fmt,##args)
+#else
+#define PRINT_DBG(fmt,args...) do{} while(0)
+#endif
+
+struct proc_dir_entry *pinctrl_proc_file;
+
+static int fh_pinctrl_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_pinctrl_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+static long fh_pinctrl_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+
+ if (unlikely(_IOC_TYPE(cmd) != PINCTRL_IOCTL_MAGIC))
+ {
+ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n",
+ __func__, _IOC_TYPE(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+
+ if (unlikely(_IOC_NR(cmd) > PINCTRL_IOCTL_MAXNR))
+ {
+ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ {
+ ret = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+ }
+ else if(_IOC_DIR(cmd) & _IOC_WRITE)
+ {
+ ret = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+ }
+
+ if(ret)
+ {
+ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -EACCES);
+ return -EACCES;
+ }
+
+ switch(cmd)
+ {
+
+ }
+
+ return ret;
+}
+
+static const struct file_operations fh_pinctrl_fops =
+{
+ .owner = THIS_MODULE,
+ .open = fh_pinctrl_open,
+ .release = fh_pinctrl_release,
+ .unlocked_ioctl = fh_pinctrl_ioctl,
+};
+
+static struct miscdevice fh_pinctrl_misc =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_NAME,
+ .fops = &fh_pinctrl_fops,
+};
+
+static void del_char(char* str,char ch)
+{
+ char *p = str;
+ char *q = str;
+ while(*q)
+ {
+ if (*q !=ch)
+ {
+ *p++ = *q;
+ }
+ q++;
+ }
+ *p='\0';
+}
+
+static void print_usage(void)
+{
+ pr_err("[dev/mux], [dev name], [mux name], [func sel]\n");
+ pr_err("[pupd], [pin name], [up|down|none], 0\n");
+ pr_err("[ds], [pin name] [ds_val(0~7)], 0\n");
+}
+
+static ssize_t fh_pinctrl_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off)
+{
+ int i;
+ char message[32] = {0};
+ char * const delim = ",";
+ char *cur = message;
+ char* param_str[4];
+ unsigned long param[4];
+
+ len = (len > 32) ? 32 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for(i=0; i<4; i++)
+ {
+ param_str[i] = strsep(&cur, delim);
+ if(!param_str[i])
+ {
+ pr_err("%s: ERROR: parameter[%d] is empty\n", __func__, i);
+ print_usage();
+ return -EINVAL;
+ }
+ else
+ {
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ }
+ }
+
+ if (!strcmp(param_str[0], "dev")) {
+ fh_pinctrl_sdev(param_str[1], 0);
+ } else if (!strcmp(param_str[0], "mux")) {
+ int ret = (u32)kstrtoul(param_str[3], 10, &param[3]);
+ if (ret || param[3] < 0) {
+ pr_err("ERROR: parameter[3] is incorrect\n");
+ return -EINVAL;
+ }
+ fh_pinctrl_smux(param_str[1], param_str[2], param[3], 0);
+ } else if (!strcmp(param_str[0], "pupd")) {
+ if (!strcmp(param_str[2], "up"))
+ param[2] = PUPD_UP;
+ else if (!strcmp(param_str[2], "down"))
+ param[2] = PUPD_DOWN;
+ else if (!strcmp(param_str[2], "none"))
+ param[2] = PUPD_NONE;
+ else {
+ pr_err("usage pupd, [pin name], [up|down|none], 0");
+ return -EINVAL;
+ }
+ if (!fh_pinctrl_spupd(param_str[1], param[2]))
+ pr_info("PIN: %s pupd: %s\n", param_str[1],
+ param_str[2]);
+ } else if (!strcmp(param_str[0], "ds")) {
+ int ret = kstrtoul(param_str[2], 10, &param[2]);
+ if (ret || param[2] < 0) {
+ pr_err("usage: ds, [pin name] [ds_val(0~7)], 0\n");
+ return -EINVAL;
+ }
+ if (!fh_pinctrl_sds(param_str[1], param[2]))
+ pr_info("PIN: %s ds: %ld\n", param_str[1], param[2]);
+ } else {
+ pr_err("ERROR: parameter[0] is incorrect\n");
+ print_usage();
+ return -EINVAL;
+ }
+ return len;
+}
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter = 0;
+ if (*pos == 0)
+ return &counter;
+ else
+ {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+
+ fh_pinctrl_prt(sfile);
+ return 0;
+}
+
+static const struct seq_operations isp_seq_ops =
+{
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_pinctrl_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &isp_seq_ops);
+}
+
+static struct file_operations fh_pinctrl_proc_ops =
+{
+ .owner = THIS_MODULE,
+ .open = fh_pinctrl_proc_open,
+ .read = seq_read,
+ .write = fh_pinctrl_proc_write,
+ .release = seq_release,
+};
+
+
+static int fh_pinctrl_probe(struct platform_device *pdev)
+{
+ int err;
+
+ err = misc_register(&fh_pinctrl_misc);
+
+ if(err < 0)
+ {
+ pr_err("%s: ERROR: %s registration failed",
+ __func__, DEVICE_NAME);
+ return -ENXIO;
+ }
+
+ pinctrl_proc_file = proc_create(FH_PINCTRL_PROC_FILE, 0644, NULL ,
+ &fh_pinctrl_proc_ops);
+
+ if (!pinctrl_proc_file) {
+ pr_err("%s: ERROR: %s proc file create failed", __func__, DEVICE_NAME);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __exit fh_pinctrl_remove(struct platform_device *pdev)
+{
+ misc_deregister(&fh_pinctrl_misc);
+ return 0;
+}
+
+static struct platform_driver fh_pinctrl_driver =
+{
+ .driver =
+ {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = fh_pinctrl_probe,
+ .remove = __exit_p(fh_pinctrl_remove),
+};
+
+static int __init fh_pinctrl_dev_init(void)
+{
+ return platform_driver_register(&fh_pinctrl_driver);
+}
+
+static void __exit fh_pinctrl_dev_exit(void)
+{
+
+ platform_driver_unregister(&fh_pinctrl_driver);
+
+}
+
+module_init(fh_pinctrl_dev_init);
+module_exit(fh_pinctrl_dev_exit);
+
+
+MODULE_AUTHOR("fullhan");
+
+MODULE_DESCRIPTION("FH PINCTRL driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
diff --git a/drivers/misc/fh_pinctrl_dev.h b/drivers/misc/fh_pinctrl_dev.h
new file mode 100644
index 00000000..8fbf6c0e
--- /dev/null
+++ b/drivers/misc/fh_pinctrl_dev.h
@@ -0,0 +1,18 @@
+
+#ifndef FH_PINCTRL_DEV_H_
+#define FH_PINCTRL_DEV_H_
+
+#include <linux/slab.h>
+#include <linux/ioctl.h>
+#include <mach/pinctrl.h>
+
+
+#define DEVICE_NAME "fh_pinctrl"
+
+
+#define PINCTRL_IOCTL_MAGIC 'p'
+
+#define PINCTRL_IOCTL_MAXNR 8
+
+
+#endif /* FH_PINCTRL_DEV_H_ */
diff --git a/drivers/misc/fh_sadc.c b/drivers/misc/fh_sadc.c
new file mode 100644
index 00000000..e004f53c
--- /dev/null
+++ b/drivers/misc/fh_sadc.c
@@ -0,0 +1,604 @@
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/miscdevice.h>
+#include <mach/fh_sadc_plat.h>
+
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include "fh_sadc.h"
+#include <mach/pmu.h>
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+#define wrap_readl(wrap, name) \
+ __raw_readl(&(((struct wrap_sadc_reg *)wrap->regs)->name))
+
+#define wrap_writel(wrap, name, val) \
+ __raw_writel((val), &(((struct wrap_sadc_reg *)wrap->regs)->name))
+
+
+#define IOCTL_GET_SADC_DATA 1
+#define IOCTL_SADC_POWER_DOWN 0xff
+#define SADC_WRAP_BASE (0xf1200000)
+#define SADC_IRQn (23)
+#define SADC_MAX_CONTROLLER (1)
+#define SADC_STATUS_COLESD (0)
+#define SADC_STATUS_OPEN (1)
+#define FH_SADC_PLAT_DEVICE_NAME "fh_sadc"
+#define FH_SADC_MISC_DEVICE_NAME "fh_sadc"
+
+/****************************************************************************
+* ADT section
+* add definition of user defined Data Type that only be used in this file here
+***************************************************************************/
+struct sadc_info {
+ int channel;
+ int sadc_data;
+};
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc,\
+ u32 channel, u16 *buf);
+static int fh_sadc_open(struct inode *inode, struct file *file);
+static int fh_sadc_release(struct inode *inode, struct file *filp);
+static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,\
+ unsigned long arg);
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+static struct wrap_sadc_obj fh_sadc_obj;
+
+static const struct file_operations fh_sadc_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_sadc_open,
+ .release = fh_sadc_release,
+ .unlocked_ioctl = fh_sadc_ioctl,
+};
+
+static struct miscdevice fh_sadc_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = FH_SADC_MISC_DEVICE_NAME,
+ .fops = &fh_sadc_fops,
+};
+
+/*****************************************************************************
+ *
+ *
+ * function body
+ *
+ *
+ *****************************************************************************/
+u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc, u32 channel,
+ u16 *buf) {
+ u32 xainsel = 1 << channel;
+ u32 xversel = 0;
+ u32 xpwdb = 1;
+ /*cnt*/
+ u32 sel2sam_pre_cnt = 2;
+ u32 sam_cnt = 2;
+ u32 sam2sel_pos_cnt = 2;
+ /*time out*/
+ u32 eoc_tos = 0xff;
+ u32 eoc_toe = 0xff;
+ u32 time_out = 0xffff;
+ /*set isr en..*/
+ u32 sadc_isr = 0x01;
+ /*start*/
+ u32 sadc_cmd = 0x01;
+ /*get data*/
+ u32 temp_data = 0;
+ u32 ret_time;
+
+ reinit_completion(&sadc->done);
+ /*control...*/
+ wrap_writel(sadc, sadc_control, xainsel | (xversel << 8) \
+ | (xpwdb << 12));
+
+ wrap_writel(sadc, sadc_cnt,
+ sel2sam_pre_cnt | (sam_cnt << 8) | \
+ (sam2sel_pos_cnt << 16));
+
+ wrap_writel(sadc, sadc_timeout,
+ eoc_tos | (eoc_toe << 8) | (time_out << 16));
+
+ wrap_writel(sadc, sadc_ier, sadc_isr);
+
+ wrap_writel(sadc, sadc_cmd, sadc_cmd);
+
+ ret_time = wait_for_completion_timeout(&sadc->done, 5000);
+ if (ret_time == 0) {
+ printk(KERN_ERR "sadc timeout..\n");
+ return SADC_TIMEOUT;
+ }
+
+ switch (channel) {
+ case 0:
+ case 1:
+ /*read channel 0 1*/
+ temp_data = wrap_readl(sadc, sadc_dout0);
+ break;
+
+ case 2:
+ case 3:
+ /*read channel 2 3*/
+ temp_data = wrap_readl(sadc, sadc_dout1);
+ break;
+
+ case 4:
+ case 5:
+ /*read channel 4 5*/
+ temp_data = wrap_readl(sadc, sadc_dout2);
+ break;
+
+ case 6:
+ case 7:
+ /*read channel 6 7*/
+ temp_data = wrap_readl(sadc, sadc_dout3);
+ break;
+ default:
+ break;
+ }
+ if (channel % 2) {
+ /*read low 16bit*/
+ *buf = (u16) (temp_data & 0xffff);
+ } else {
+ /*read high 16bit*/
+ *buf = (u16) (temp_data >> 16);
+ }
+ return 0;
+
+}
+
+int fh_sadc_enable(void)
+{
+ u32 control_reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ control_reg = wrap_readl(sadc, sadc_control);
+ control_reg |= 1 << 12;
+ wrap_writel(sadc, sadc_control, control_reg);
+ return 0;
+}
+
+int fh_sadc_disable(void)
+{
+ u32 control_reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ control_reg = wrap_readl(sadc, sadc_control);
+ control_reg &= ~(1 << 12);
+ wrap_writel(sadc, sadc_control, control_reg);
+ return 0;
+}
+
+static irqreturn_t fh_sadc_isr(int irq, void *dev_id)
+{
+
+ u32 isr_status;
+ struct wrap_sadc_obj *sadc = (struct wrap_sadc_obj *) dev_id;
+
+ isr_status = wrap_readl(sadc, sadc_int_status);
+ if (isr_status & 0x01) {
+
+ u32 sadc_isr = 0x00;
+ wrap_writel(sadc, sadc_ier, sadc_isr);
+
+ wrap_writel(sadc, sadc_int_status, isr_status);
+ complete(&(sadc->done));
+ } else {
+
+ printk(KERN_ERR "sadc maybe error!\n");
+
+ }
+ return IRQ_HANDLED;
+}
+
+long fh_sadc_get_value(int channel)
+{
+ unsigned int ret;
+ long w = 0;
+ u16 ad_raw_data;
+ if (channel < 0) {
+ printk(KERN_ERR "ERROR: %s, sadc channel no %d is incorrect\n",
+ __func__, channel);
+ return 0;
+ }
+
+ fh_sadc_enable();
+
+ ret = fh_sadc_isr_read_data(&fh_sadc_obj, channel, &ad_raw_data);
+
+ if (ret != 0) {
+ printk(KERN_INFO "sadc error code:0x%x\n", ret);
+ } else {
+ w = ad_raw_data * fh_sadc_obj.refvol / fh_sadc_obj.activebit;
+ printk(KERN_INFO "the value of sadc is: %ld\n", w);
+ }
+
+ return w;
+}
+
+static void del_char(char *str, char ch)
+{
+ char *p = str;
+ char *q = str;
+ while (*q) {
+ if (*q != ch)
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+}
+
+static ssize_t fh_sadc_proc_write(struct file *filp, const char *buf,
+ size_t len, loff_t *off)
+{
+ char message[32] = {0};
+ char * const delim = ",";
+ char *cur = message, *power_str;
+ int power;
+ unsigned int str_len;
+ str_len = 10;
+ len = (len > 32) ? 32 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ power_str = strsep(&cur, delim);
+ if (!power_str) {
+ pr_err("%s: ERROR: parameter is empty\n", __func__);
+ return -EINVAL;
+ } else {
+ del_char(power_str, ' ');
+ del_char(power_str, '\n');
+ power = kstrtouint(power_str, 0, &str_len);
+ if (power < 0) {
+ pr_err("%s: ERROR: parameter is incorrect\n",\
+ __func__);
+ return -EINVAL;
+ }
+ }
+
+ power ? fh_sadc_enable() : fh_sadc_disable();
+
+ return len;
+}
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+ counter = 0;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int i;
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 ret;
+
+ reg = (wrap_readl(sadc, sadc_control) & 0x1000);
+
+ seq_printf(sfile, "\nSADC Status:\n");
+ seq_printf(sfile, "Power %s\n\n", reg ? "up" : "down");
+
+ for (i = 0; i < 8; i++) {
+ u16 ad_raw_data;
+ ret = fh_sadc_isr_read_data(&fh_sadc_obj, i, &ad_raw_data);
+ if (ret != 0)
+ seq_printf(sfile, "sadc error code:0x%x\n", ret);
+ else
+ seq_printf(sfile, "channel: %d \tvalue: %u\n", i,
+ ad_raw_data * fh_sadc_obj.refvol / fh_sadc_obj.activebit);
+ }
+ return 0;
+}
+
+static const struct seq_operations isp_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_sadc_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &isp_seq_ops);
+}
+
+static const struct file_operations fh_sadc_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_sadc_proc_open,
+ .read = seq_read,
+ .write = fh_sadc_proc_write,
+ .release = seq_release,
+};
+
+
+static struct of_device_id const fh_sadc_of_match[] = {
+ { .compatible = "fh,fh-sadc" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fh_sadc_of_match);
+
+
+static int fh_sadc_probe(struct platform_device *pdev)
+{
+ int err;
+#ifdef CONFIG_USE_OF
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct fh_sadc_platform_data *plat_data;
+ struct resource *res;
+#endif
+ struct clk *sadc_clk;
+
+
+ sadc_clk = clk_get(&pdev->dev, "sadc_clk");
+ if (IS_ERR(sadc_clk)) {
+ err = PTR_ERR(sadc_clk);
+ return -EPERM;
+ }
+ clk_prepare_enable(sadc_clk);
+ fh_sadc_obj.clk = sadc_clk;
+#ifdef CONFIG_USE_OF
+ match = of_match_device(fh_sadc_of_match, &pdev->dev);
+ if (!match) {
+ pr_info("Failed to find sadc controller\n");
+ return -ENODEV;
+ }
+
+ fh_sadc_obj.regs = of_iomap(np, 0);
+ if (fh_sadc_obj.regs == NULL) {
+ err = -ENXIO;
+ return err;
+ }
+
+
+ fh_sadc_obj.irq_no = irq_of_parse_and_map(np, 0);
+ if (fh_sadc_obj.irq_no < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ goto fail_no_ioremap;
+ }
+ of_property_read_u32(np, "ref-vol", &fh_sadc_obj.refvol);
+ of_property_read_u32(np, "active-bit", &fh_sadc_obj.activebit);
+#else
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "sadc get platform source error..\n");
+ return -ENODEV;
+ }
+ plat_data = pdev->dev.platform_data;
+ if (!plat_data) {
+ dev_err(&pdev->dev, "sadc get platform data error..\n");
+ return -ENODEV;
+ }
+
+ fh_sadc_obj.refvol = plat_data->ref_vol;
+ fh_sadc_obj.activebit = plat_data->active_bit;
+ fh_sadc_obj.irq_no = platform_get_irq(pdev, 0);
+ fh_sadc_obj.irq_no = irq_create_mapping(NULL,
+ fh_sadc_obj.irq_no);
+ if (fh_sadc_obj.irq_no < 0) {
+ dev_warn(&pdev->dev, "sadc interrupt is not available.\n");
+ return fh_sadc_obj.irq_no;
+ }
+
+ res = request_mem_region(res->start, resource_size(res),
+ pdev->name);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "sadc region already claimed\n");
+ return -EBUSY;
+ }
+
+ fh_sadc_obj.regs = ioremap(res->start, resource_size(res));
+ if (fh_sadc_obj.regs == NULL) {
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+#endif
+ strncpy(fh_sadc_obj.isr_name, "sadc", sizeof("sadc"));
+ err = request_irq(fh_sadc_obj.irq_no, fh_sadc_isr, IRQF_NO_THREAD,
+ fh_sadc_obj.isr_name, &fh_sadc_obj);
+
+ if (err) {
+ dev_err(&pdev->dev, "request_irq:%d failed, %d\n",
+ fh_sadc_obj.irq_no, err);
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+
+ init_completion(&fh_sadc_obj.done);
+ mutex_init(&fh_sadc_obj.sadc_lock);
+ fh_sadc_obj.active_channel_no = 0;
+
+
+ err = misc_register(&fh_sadc_misc);
+
+ if (err < 0) {
+ pr_err("%s: ERROR: %s registration failed", __func__,
+ FH_SADC_MISC_DEVICE_NAME);
+ err = -ENXIO;
+ goto misc_error;
+ }
+
+ fh_sadc_obj.proc_file = proc_create(FH_SADC_PROC_FILE,
+ S_IRUGO, NULL, &fh_sadc_proc_ops);
+
+ if (!fh_sadc_obj.proc_file)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, "SADC");
+
+ pr_info("SADC probe successful, IO base addr: %p\n",
+ fh_sadc_obj.regs);
+ return 0;
+
+misc_error:
+ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj);
+
+fail_no_ioremap:
+ iounmap(fh_sadc_obj.regs);
+
+
+ return err;
+}
+
+static int __exit fh_sadc_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ if (fh_sadc_obj.clk) {
+ clk_disable_unprepare(fh_sadc_obj.clk);
+ clk_put(fh_sadc_obj.clk);
+ }
+ misc_deregister(&fh_sadc_misc);
+ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj);
+ proc_remove(fh_sadc_obj.proc_file);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+ iounmap(fh_sadc_obj.regs);
+ return 0;
+
+}
+
+
+static int fh_sadc_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_sadc_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg) {
+
+ u32 ad_data;
+ u32 control_reg;
+ u16 ad_raw_data;
+ struct sadc_info sadc_info;
+
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ mutex_lock(&sadc->sadc_lock);
+ if (cmd == IOCTL_GET_SADC_DATA) {
+ if (copy_from_user((void *) &sadc_info, (void __user*) arg,
+ sizeof(sadc_info))) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EFAULT;
+ }
+ if ((wrap_readl(sadc, sadc_status2) & 0x10)) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EBUSY;
+ }
+ fh_sadc_isr_read_data(&fh_sadc_obj, sadc_info.channel,\
+ &ad_raw_data);
+ ad_data = ad_raw_data * fh_sadc_obj.refvol;
+ ad_data /= fh_sadc_obj.activebit;
+ sadc_info.sadc_data = ad_data;
+ if (put_user(sadc_info.sadc_data,
+ (int __user *)(&((struct sadc_info *)arg)\
+ ->sadc_data))) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EFAULT;
+ }
+ }
+
+ else if (cmd == IOCTL_SADC_POWER_DOWN) {
+ control_reg = wrap_readl(sadc, sadc_control);
+ control_reg &= ~(1 << 12);
+ wrap_writel(sadc, sadc_control, control_reg);
+ }
+ mutex_unlock(&sadc->sadc_lock);
+ return 0;
+}
+
+
+/*******************
+ *
+ *
+ *add platform cause of i need the board info...
+ *in the probe function. i will register the sadc
+ *misc drive...then the app can open the sadc misc device..
+ *
+ ******************/
+static struct platform_driver fh_sadc_driver = {
+ .driver = {
+ .name = FH_SADC_PLAT_DEVICE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = fh_sadc_of_match,
+ },
+ .probe = fh_sadc_probe,
+ .remove = __exit_p(fh_sadc_remove),
+};
+
+
+
+static int __init fh_sadc_init(void)
+{
+ return platform_driver_register(&fh_sadc_driver);
+}
+
+static void __exit fh_sadc_exit(void)
+{
+
+ platform_driver_unregister(&fh_sadc_driver);
+
+}
+
+module_init(fh_sadc_init);
+module_exit(fh_sadc_exit);
+
+MODULE_DESCRIPTION("fullhan sadc device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("tangyh@fullhan.com");
+MODULE_ALIAS("platform:FH_sadc");
diff --git a/drivers/misc/fh_sadc.h b/drivers/misc/fh_sadc.h
new file mode 100644
index 00000000..81f8e14d
--- /dev/null
+++ b/drivers/misc/fh_sadc.h
@@ -0,0 +1,75 @@
+#ifndef FH_SADC_H_
+#define FH_SADC_H_
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/bug.h>
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+
+/****************************************************************************
+ * #define section
+ * add constant #define here if any
+ ***************************************************************************/
+#define FH_SADC_PROC_FILE "driver/sadc"
+#define MAX_CHANNEL_NO (8)
+#define LOOP_MODE (0x55)
+#define ISR_MODE (0xAA)
+
+
+#define SADC_TIMEOUT 0x55
+/****************************************************************************
+ * ADT section
+ * add Abstract Data Type definition here
+ ***************************************************************************/
+
+struct wrap_sadc_reg {
+ u32 sadc_cmd;
+ u32 sadc_control;
+ u32 sadc_ier;
+ u32 sadc_int_status;
+ u32 sadc_dout0;
+ u32 sadc_dout1;
+ u32 sadc_dout2;
+ u32 sadc_dout3;
+ u32 sadc_debuge0;
+ u32 sadc_status;
+ u32 sadc_cnt;
+ u32 sadc_timeout;
+ u32 sadc_status2;
+};
+
+
+struct wrap_sadc_obj {
+ void *regs;
+ u32 irq_no;
+ u32 active_channel_no;
+ u32 active_channel_status;
+ uint16_t channel_data[MAX_CHANNEL_NO];
+ u32 error_rec;
+ u32 en_isr;
+ u32 sample_mode;
+ spinlock_t lock;
+ struct mutex sadc_lock;
+ struct completion done;
+ struct proc_dir_entry *proc_file;
+ u32 activebit;
+ u32 refvol;
+ struct clk *clk;
+ char isr_name[10];
+};
+
+long fh_sadc_get_value(int channel);
+
+
+#endif /* fh_SADC_H_ */
diff --git a/drivers/misc/fh_sadc_v2.c b/drivers/misc/fh_sadc_v2.c
new file mode 100644
index 00000000..0df582be
--- /dev/null
+++ b/drivers/misc/fh_sadc_v2.c
@@ -0,0 +1,1184 @@
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/miscdevice.h>
+#include <mach/fh_sadc_plat.h>
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include "fh_sadc_v2.h"
+#include <mach/pmu.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+#define wrap_readl(wrap, name) \
+ __raw_readl(&(((struct wrap_sadc_reg *)wrap->regs)->name))
+
+#define wrap_writel(wrap, name, val) \
+ __raw_writel((val), &(((struct wrap_sadc_reg *)wrap->regs)->name))
+
+#define SADC_CHANNEL_NUM (8)
+
+#define IOCTL_GET_SINGLE_SADC_DATA 0x1
+#define IOCTL_CONTINUE_SADC_CFG 0x3
+#define IOCTL_CONTINUE_SADC_START 0x4
+#define IOCTL_CONTINUE_SADC_END 0x5
+#ifdef CONFIG_FH_SADC_V21
+#define IOCTL_HIT_SADC_CFG 0x6
+#endif
+#define IOCTL_SADC_POWER_DOWN 0xff
+#define SADC_WRAP_BASE (SADC_REG_BASE)
+#define SADC_IRQn (23)
+#define SADC_MAX_CONTROLLER (1)
+#define SADC_STATUS_COLESD (0)
+#define SADC_STATUS_OPEN (1)
+
+#define FH_SADC_PLAT_DEVICE_NAME "fh_sadc"
+#define FH_SADC_MISC_DEVICE_NAME "fh_sadc"
+/*void (*g_sadc_get_continue_data)(u8 channel, u32 value) = NULL;*/
+/*void (*g_sadc_get_hit_data)(u8 channel, u32 value) = NULL;*/
+
+/*#define FH_SADC_DEBUG*/
+
+/****************************************************************************
+* ADT section
+* add definition of user defined Data Type that only be used in this file here
+***************************************************************************/
+struct sadc_info {
+ int channel;
+ int sadc_data;
+};
+
+struct sadc_continue_cfg {
+ u32 channel_cfg;
+ u32 continue_time; /*ms*/
+ u32 glitch_value; /*mv*/
+ u32 glitch_time; /*count*/
+ u32 eq_flag;
+ u32 zero_value; /*ms*/
+ u32 precision; /*0xfff*/
+ u32 powerdown;
+};
+
+struct sadc_continue_ctrl {
+ struct sadc_info usrdata;
+ u32 flag;
+};
+
+
+#ifdef CONFIG_FH_SADC_V21
+struct sadc_hit_data_cfg {
+ u8 channel_cfg;
+ u8 value_en;
+ u16 hit_gap;/*mv*/
+ u16 value[8];/*mv*/
+};
+#endif
+
+struct sadc_continue_ctrl g_sadc_data[SADC_CHANNEL_NUM];
+u32 g_sadc_debug;
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc,\
+ u32 channel, u16 *buf);
+static int fh_sadc_open(struct inode *inode, struct file *file);
+static int fh_sadc_release(struct inode *inode, struct file *filp);
+static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,\
+ unsigned long arg);
+static int fh_sadc_read(struct file *filp, char __user *buf,
+ size_t len, loff_t *off);
+
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+static struct wrap_sadc_obj fh_sadc_obj;
+
+static const struct file_operations fh_sadc_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_sadc_open,
+ .read = fh_sadc_read,
+ .release = fh_sadc_release,
+ .unlocked_ioctl = fh_sadc_ioctl,
+};
+
+static struct miscdevice fh_sadc_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = FH_SADC_MISC_DEVICE_NAME,
+ .fops = &fh_sadc_fops,
+};
+
+/*****************************************************************************
+ *
+ *
+ * function body
+ *
+ *
+ *****************************************************************************/
+u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc, u32 channel,
+ u16 *buf) {
+ u32 xainsel = 1 << channel;
+ u32 xversel = 0;
+ u32 xpwdb = 1;
+ /*cnt*/
+ u32 sel2sam_pre_cnt = 2;
+ u32 sam_cnt = 2;
+ u32 sam2sel_pos_cnt = 2;
+ /*time out*/
+ u32 eoc_tos = 0xff;
+ u32 eoc_toe = 0xff;
+ u32 time_out = 0xffff;
+ /*set isr en..*/
+ u32 sadc_isr = 0x01;
+ /*start*/
+ u32 sadc_cmd = 0x01;
+ /*get data*/
+ u32 temp_data = 0;
+ u32 ret_time;
+
+ reinit_completion(&sadc->done);
+ /*control...*/
+ wrap_writel(sadc, sadc_control, xainsel | (xversel << 8) \
+ | (xpwdb << 12));
+
+ wrap_writel(sadc, sadc_cnt,
+ sel2sam_pre_cnt | (sam_cnt << 8) | \
+ (sam2sel_pos_cnt << 16));
+
+ wrap_writel(sadc, sadc_timeout,
+ eoc_tos | (eoc_toe << 8) | (time_out << 16));
+
+ wrap_writel(sadc, sadc_ier, sadc_isr);
+
+ wrap_writel(sadc, sadc_cmd, sadc_cmd);
+ ret_time = wait_for_completion_timeout(&sadc->done, 5000);
+ if (ret_time == 0) {
+ printk(KERN_ERR "sadc timeout..\n");
+ return SADC_TIMEOUT;
+ }
+
+ switch (channel) {
+ case 0:
+ case 1:
+ /*read channel 0 1*/
+ temp_data = wrap_readl(sadc, sadc_dout0);
+ break;
+
+ case 2:
+ case 3:
+ /*read channel 2 3*/
+ temp_data = wrap_readl(sadc, sadc_dout1);
+ break;
+
+ case 4:
+ case 5:
+ /*read channel 4 5*/
+ temp_data = wrap_readl(sadc, sadc_dout2);
+ break;
+
+ case 6:
+ case 7:
+ /*read channel 6 7*/
+ temp_data = wrap_readl(sadc, sadc_dout3);
+ break;
+ default:
+ break;
+ }
+ if (channel % 2) {
+ /*read low 16bit*/
+ *buf = (u16) (temp_data & 0xffff);
+ } else {
+ /*read high 16bit*/
+ *buf = (u16) (temp_data >> 16);
+ }
+ return 0;
+
+}
+
+
+/* 0:single mode;1:continue mode*/
+int fh_sadc_mode_set(u32 mode)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_model);
+ if (mode)
+ reg |= 1;
+ else
+ reg &= (~1);
+ wrap_writel(sadc, sadc_model, reg);
+ return 0;
+}
+
+int fh_sadc_lpc_en_set(u32 lpc_flag)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_chn_cfg);
+ if (lpc_flag)
+ reg |= (1 << 28);
+ else
+ reg &= (~(1 << 28));
+ wrap_writel(sadc, sadc_chn_cfg, reg);
+ return 0;
+}
+
+u32 fh_sadc_lpc_en_get(void)
+{
+ u32 reg;
+ u32 ret;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_chn_cfg);
+ reg &= (1 << 28);
+ ret = reg >> 28;
+ return ret;
+}
+
+int fh_sadc_scan_delta(u32 scan_delta)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 value;
+
+ value = ((u32)scan_delta*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ if (value > 0x3f)
+ value = 0x3f;
+ reg = wrap_readl(sadc, sadc_chn_cfg1);
+ reg &= (~(0x3f<<0));
+ reg |= value ;
+ wrap_writel(sadc, sadc_chn_cfg1, reg);
+ return 0;
+}
+
+
+int fh_sadc_glitch_en_set(u32 glitch_flag)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_chn_cfg);
+ if (glitch_flag)
+ reg |= (1 << 27);
+ else
+ reg &= (~(1 << 27));
+ wrap_writel(sadc, sadc_chn_cfg, reg);
+ return 0;
+}
+
+u32 fh_sadc_glitch_en_get(void)
+{
+ u32 reg;
+ u32 ret;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_chn_cfg);
+ reg &= (1 << 27);
+ ret = reg >> 27;
+ return ret;
+}
+
+int fh_sadc_scan_start(void)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_scan_en);
+ reg |= (1 << 0);
+ wrap_writel(sadc, sadc_scan_en, reg);
+ return 0;
+}
+
+int fh_sadc_scan_end(void)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_scan_en);
+ reg |= (1 << 1);
+ wrap_writel(sadc, sadc_scan_en, reg);
+ return 0;
+}
+
+int fh_sadc_scan_power_cnt(u8 scan_power_cnt)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_chn_cfg1);
+ reg &= (~(0xff<<8));
+ reg |= (scan_power_cnt << 8);
+ wrap_writel(sadc, sadc_chn_cfg1, reg);
+ return 0;
+}
+
+
+int fh_sadc_cons_ch_eq_set(u32 chn_num)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, sadc_glitch_cfg);
+ reg |= (chn_num&0xff);
+ wrap_writel(sadc, sadc_glitch_cfg, reg);
+ return 0;
+}
+
+int fh_sadc_set_act_bit(u32 act_bit)
+{
+ u32 reg;
+ u32 value;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if (act_bit > 12)
+ value = 12;
+ else
+ value = act_bit;
+ value = (~(1<<value))&0xfff;
+ reg = wrap_readl(sadc, sadc_glitch_cfg);
+ reg &= (~(0xfff<<8));
+ reg |= (value<<8);
+ wrap_writel(sadc, sadc_glitch_cfg, reg);
+ return 0;
+}
+
+int fh_sadc_set_continuous_time(u32 continuous_time)
+{
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ struct clk *sadc_clk;
+ u32 value;
+ u32 rate;
+
+ sadc_clk = clk_get(NULL, "sadc_clk");
+ if (IS_ERR(sadc_clk))
+ return -EPERM;
+ rate = clk_get_rate(sadc_clk);
+ value = continuous_time*(rate/1000);
+ /*value = continuous_time*(1000000/1000);*/
+ wrap_writel(sadc, sadc_continuous_time, value);
+ return 0;
+}
+
+int fh_sadc_set_glitch_time(u32 glitch_time)
+{
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ wrap_writel(sadc, sadc_glitch_time, glitch_time);
+ return 0;
+}
+
+int fh_sadc_set_zero_value(u32 zero_value)
+{
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 value;
+ u32 reg;
+
+
+ value = (zero_value * fh_sadc_obj.activebit) / fh_sadc_obj.refvol;
+ value &= 0xfff;
+ reg = wrap_readl(sadc, sadc_glitch_cfg);
+ reg &= (~(0xfff<<20));
+ reg |= (value<<20);
+ wrap_writel(sadc, sadc_glitch_cfg, reg);
+ return 0;
+}
+
+#ifdef CONFIG_FH_SADC_V21
+int fh_sadc_hit_data_config(struct sadc_hit_data_cfg *hit_data)
+{
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 value;
+ u32 value1;
+ u32 reg;
+
+ value = hit_data->hit_gap;
+ value = (value*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value &= 0xfff;
+ reg = value|(hit_data->value_en << 16)|(hit_data->channel_cfg << 24);
+ wrap_writel(sadc, sadc_hit_cfg, reg);
+
+ value = hit_data->value[0];
+ value = (value*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value &= 0xfff;
+
+ value1 = hit_data->value[1];
+ value1 = (value1*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value1 &= 0xfff;
+ reg = value | (value1 << 16);
+
+ wrap_writel(sadc, sadc_hit_value0, reg);
+
+ value = hit_data->value[2];
+ value = (value*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value &= 0xfff;
+
+ value1 = hit_data->value[3];
+ value1 = (value1*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value1 &= 0xfff;
+ reg = value | (value1 << 16);
+
+ wrap_writel(sadc, sadc_hit_value1, reg);
+
+ value = hit_data->value[4];
+ value = (value*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value &= 0xfff;
+
+ value1 = hit_data->value[5];
+ value1 = (value1*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value1 &= 0xfff;
+ reg = value | (value1 << 16);
+
+ wrap_writel(sadc, sadc_hit_value2, reg);
+
+ value = hit_data->value[6];
+ value = (value*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value &= 0xfff;
+
+ value1 = hit_data->value[7];
+ value1 = (value1*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value1 &= 0xfff;
+ reg = value | (value1 << 16);
+
+ wrap_writel(sadc, sadc_hit_value3, reg);
+
+ reg = wrap_readl(sadc, sadc_ier);
+ reg &= (~(0xff<<24));
+ reg |= (hit_data->value_en << 24);
+ wrap_writel(sadc, sadc_ier, reg);
+ return 0;
+}
+#endif
+
+int fh_sadc_enable(void)
+{
+ u32 control_reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ control_reg = wrap_readl(sadc, sadc_control);
+ control_reg |= 1 << 12;
+ wrap_writel(sadc, sadc_control, control_reg);
+ return 0;
+}
+
+int fh_sadc_disable(void)
+{
+ u32 control_reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ control_reg = wrap_readl(sadc, sadc_control);
+ control_reg &= ~(1 << 12);
+ wrap_writel(sadc, sadc_control, control_reg);
+ return 0;
+}
+
+
+u32 fh_sadc_default_config(void)
+{
+ u32 xversel = 0;
+ u32 xpwdb = 1;
+ /*cnt*/
+ u32 sel2sam_pre_cnt = 2;
+ u32 sam_cnt = 2;
+ u32 sam2sel_pos_cnt = 2;
+ /*time out*/
+ u32 eoc_tos = 0xff;
+ u32 eoc_toe = 0xff;
+ u32 time_out = 0xffff;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ /*sadc act bit default 12bit*/
+ fh_sadc_set_act_bit(12);
+ /*control...*/
+ wrap_writel(sadc, sadc_control, (xversel << 8) \
+ | (xpwdb << 12));
+
+ wrap_writel(sadc, sadc_cnt,
+ sel2sam_pre_cnt | (sam_cnt << 8) | \
+ (sam2sel_pos_cnt << 16));
+
+ wrap_writel(sadc, sadc_timeout,
+ eoc_tos | (eoc_toe << 8) | (time_out << 16));
+
+
+ return 0;
+}
+
+static irqreturn_t fh_sadc_isr(int irq, void *dev_id)
+{
+
+ u32 isr_status;
+ u32 temp_data = 0;
+ u32 temp_data1 = 0;
+ u32 channel = 0;
+ u32 data = 0;
+ u32 data1 = 0;
+ struct wrap_sadc_obj *sadc = (struct wrap_sadc_obj *) dev_id;
+
+ isr_status = wrap_readl(sadc, sadc_int_status);
+ /*single intc*/
+ if (isr_status & 0x01) {
+ u32 sadc_isr = 0x00;
+ wrap_writel(sadc, sadc_ier, sadc_isr);
+ wrap_writel(sadc, sadc_int_status, isr_status);
+ complete(&(sadc->done));
+ return IRQ_HANDLED;
+ }
+
+ if (isr_status & 0x10000) {
+ channel = wrap_readl(sadc, sadc_status2);
+ channel = ((channel>>12)&0x7);
+ switch (channel/2) {
+ case 0:
+ /*read channel 0 1*/
+ temp_data = wrap_readl(sadc, sadc_dout0);
+ break;
+ case 1:
+ /*read channel 2 3*/
+ temp_data = wrap_readl(sadc, sadc_dout1);
+ break;
+ case 2:
+ /*read channel 4 5*/
+ temp_data = wrap_readl(sadc, sadc_dout2);
+ break;
+ case 3:
+ /*read channel 6 7*/
+ temp_data = wrap_readl(sadc, sadc_dout3);
+ break;
+ default:
+ break;
+ }
+
+ if (channel % 2)
+ /*read low 16bit*/
+ data = (temp_data & 0xfff);
+ else
+ /*read high 16bit*/
+ data = (temp_data >> 16) & 0xfff;
+ data = (data*fh_sadc_obj.refvol)/fh_sadc_obj.activebit;
+ if (g_sadc_debug)
+ printk(KERN_ERR "channel:%x data:%dmv\n",
+ channel, data);
+ if (waitqueue_active(&fh_sadc_obj.readqueue)) {
+ if (g_sadc_data[channel].flag) {
+ g_sadc_data[channel].usrdata.sadc_data = data;
+ g_sadc_data[channel].flag = 0;
+ wake_up(&fh_sadc_obj.readqueue);
+ }
+ }
+ wrap_writel(sadc, sadc_int_status, 0x10000);
+ }
+ if (isr_status & 0x100000) {
+ channel = wrap_readl(sadc, sadc_status2);
+ channel = ((channel>>12)&0x7);
+ switch (channel/2) {
+ case 0:
+ /*read channel 0 1*/
+ temp_data1 = wrap_readl(sadc, sadc_dout0_all);
+ break;
+ case 1:
+ /*read channel 2 3*/
+ temp_data1 = wrap_readl(sadc, sadc_dout1_all);
+ break;
+ case 2:
+ /*read channel 4 5*/
+ temp_data1 = wrap_readl(sadc, sadc_dout2_all);
+ break;
+ case 3:
+ /*read channel 6 7*/
+ temp_data1 = wrap_readl(sadc, sadc_dout3_all);
+ break;
+ default:
+ break;
+ }
+
+ if (channel % 2)
+ /*read low 16bit*/
+ data1 = (temp_data1 & 0xfff);
+ else
+ /*read high 16bit*/
+ data1 = (temp_data1 >> 16) & 0xfff;
+ data1 = (data1 * fh_sadc_obj.refvol) / fh_sadc_obj.activebit;
+ if (g_sadc_debug) {
+ printk(KERN_ERR "glitch :%x data:%dmv\n",
+ channel, data1);
+ wrap_writel(sadc, sadc_int_status, 0x100000);
+ }
+ }
+#ifdef CONFIG_FH_SADC_V21
+ if (isr_status & 0xff000000) {
+ channel = wrap_readl(sadc, sadc_status2);
+ channel = ((channel>>12)&0x7);
+ switch (channel) {
+ case 0:
+ case 1:
+ /*read channel 0 1*/
+ temp_data = wrap_readl(sadc, sadc_hit_data0);
+ break;
+
+ case 2:
+ case 3:
+ /*read channel 2 3*/
+ temp_data = wrap_readl(sadc, sadc_hit_data1);
+ break;
+
+ case 4:
+ case 5:
+ /*read channel 4 5*/
+ temp_data = wrap_readl(sadc, sadc_hit_data2);
+ break;
+
+ case 6:
+ case 7:
+ /*read channel 6 7*/
+ temp_data = wrap_readl(sadc, sadc_hit_data3);
+ break;
+ default:
+ break;
+ }
+
+ if (channel % 2) {
+ /*read low 16bit*/
+ data = (temp_data & 0xfff);
+ } else {
+ /*read high 16bit*/
+ data = (temp_data >> 16) & 0xfff;
+ }
+
+ data = (data * fh_sadc_obj.refvol) / fh_sadc_obj.activebit;
+
+ if (g_sadc_debug)
+ printk(KERN_ERR "hit value channel:%x data:%dmv isr_status:%x\n",
+ channel, data, isr_status);
+ if (waitqueue_active(&fh_sadc_obj.readqueue)) {
+ if (g_sadc_data[channel].flag) {
+ g_sadc_data[channel].usrdata.sadc_data = data;
+ g_sadc_data[channel].flag = 0;
+ wake_up(&fh_sadc_obj.readqueue);
+ }
+ }
+ wrap_writel(sadc, sadc_int_status, (isr_status & 0xff000000));
+
+ }
+#endif
+ return IRQ_HANDLED;
+}
+
+long fh_sadc_get_value(int channel)
+{
+ unsigned int ret;
+ long w = 0;
+ u16 ad_raw_data;
+ if (channel < 0) {
+ printk(KERN_ERR "ERROR: %s, sadc channel no %d is incorrect\n",
+ __func__, channel);
+ return 0;
+ }
+
+ fh_sadc_enable();
+
+ ret = fh_sadc_isr_read_data(&fh_sadc_obj, channel, &ad_raw_data);
+
+ if (ret != 0) {
+ printk(KERN_INFO "sadc error code:0x%x\n", ret);
+ } else {
+ w = ad_raw_data * fh_sadc_obj.refvol / fh_sadc_obj.activebit;
+ printk(KERN_INFO "the value of sadc is: %ld\n", w);
+ }
+
+ return w;
+}
+
+static void del_char(char *str, char ch)
+{
+ char *p = str;
+ char *q = str;
+ while (*q) {
+ if (*q != ch)
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+}
+
+static ssize_t fh_sadc_proc_write(struct file *filp, const char *buf,
+ size_t len, loff_t *off)
+{
+ char message[32] = {0};
+ char * const delim = ",";
+ char *cur = message;
+ int i;
+ char *param_str[2];
+ int reg;
+ int ret;
+ unsigned long param = 0;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ len = (len > 32) ? 32 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for (i = 0; i < 2; i++) {
+ param_str[i] = strsep(&cur, delim);
+ if (!param_str[i]) {
+ pr_err("%s: ERROR: parameter[%d] is empty\n",
+ __func__, i);
+ pr_err("[debug],[channel],[pwr_down]\n");
+ return -EINVAL;
+ } else {
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ }
+ }
+ if (!strcmp(param_str[0], "debug")) {
+ ret = (u32)kstrtoul(param_str[1], 10, &param);
+ spin_lock_irq(&fh_sadc_obj.lock);
+ if (param) {
+ g_sadc_debug = 1;
+ reg = wrap_readl(sadc, sadc_ier);
+ reg |= 1<<20;
+ wrap_writel(sadc, sadc_ier, reg);
+ } else {
+ g_sadc_debug = 0;
+ reg = wrap_readl(sadc, sadc_ier);
+ reg &= (~(1<<20));
+ wrap_writel(sadc, sadc_ier, reg);
+ }
+ spin_unlock_irq(&fh_sadc_obj.lock);
+ }
+
+ if (!strcmp(param_str[0], "pwr_down")) {
+ ret = (u32)kstrtoul(param_str[1], 10, &param);
+ param ? fh_sadc_enable() : fh_sadc_disable();
+ }
+
+ return len;
+}
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+ counter = 0;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int i;
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 ret;
+
+ reg = (wrap_readl(sadc, sadc_control) & 0x1000);
+
+ seq_printf(sfile, "\nSADC Status:\n");
+ seq_printf(sfile, "Power %s\n\n", reg ? "up" : "down");
+
+ for (i = 0; i < 8; i++) {
+ u16 ad_raw_data;
+ ret = fh_sadc_isr_read_data(&fh_sadc_obj, i, &ad_raw_data);
+ if (ret != 0)
+ seq_printf(sfile, "sadc error code:0x%x\n", ret);
+ else
+ seq_printf(sfile, "channel: %d \tvalue: %u\n", i,
+ ad_raw_data * fh_sadc_obj.refvol / fh_sadc_obj.activebit);
+ }
+ return 0;
+}
+
+static const struct seq_operations isp_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_sadc_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &isp_seq_ops);
+}
+
+static const struct file_operations fh_sadc_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_sadc_proc_open,
+ .read = seq_read,
+ .write = fh_sadc_proc_write,
+ .release = seq_release,
+};
+
+static struct of_device_id const fh_sadc_of_match[] = {
+ { .compatible = "fh,fh-sadc" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fh_sadc_of_match);
+
+
+static int fh_sadc_probe(struct platform_device *pdev)
+{
+ int err;
+#ifdef CONFIG_USE_OF
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *res;
+ struct fh_sadc_platform_data *plat_data;
+#endif
+ struct clk *sadc_clk;
+
+ sadc_clk = clk_get(&pdev->dev, "sadc_clk");
+ if (IS_ERR(sadc_clk)) {
+ err = PTR_ERR(sadc_clk);
+ return -EPERM;
+ }
+ clk_prepare_enable(sadc_clk);
+ fh_sadc_obj.clk = sadc_clk;
+#ifdef CONFIG_USE_OF
+ match = of_match_device(fh_sadc_of_match, &pdev->dev);
+ if (!match) {
+ pr_info("Failed to find sadc controller\n");
+ return -ENODEV;
+ }
+
+ fh_sadc_obj.regs = of_iomap(np, 0);
+ if (fh_sadc_obj.regs == NULL) {
+ err = -ENXIO;
+ return err;
+ }
+
+ fh_sadc_obj.irq_no = irq_of_parse_and_map(np, 0);
+ if (fh_sadc_obj.irq_no < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ goto fail_no_ioremap;
+ }
+ of_property_read_u32(np, "ref-vol", &fh_sadc_obj.refvol);
+ of_property_read_u32(np, "active-bit", &fh_sadc_obj.activebit);
+#else
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "sadc get platform source error..\n");
+ return -ENODEV;
+ }
+
+ plat_data = pdev->dev.platform_data;
+ if (!plat_data) {
+ dev_err(&pdev->dev, "sadc get platform data error..\n");
+ return -ENODEV;
+ }
+
+ fh_sadc_obj.refvol = plat_data->ref_vol;
+ fh_sadc_obj.activebit = plat_data->active_bit;
+ fh_sadc_obj.irq_no = platform_get_irq(pdev, 0);
+ fh_sadc_obj.irq_no = irq_create_mapping(NULL,
+ fh_sadc_obj.irq_no);
+ if (fh_sadc_obj.irq_no < 0) {
+ dev_warn(&pdev->dev, "sadc interrupt is not available.\n");
+ return fh_sadc_obj.irq_no;
+ }
+
+ res = request_mem_region(res->start, resource_size(res),
+ pdev->name);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "sadc region already claimed\n");
+ return -EBUSY;
+ }
+
+ fh_sadc_obj.regs = ioremap(res->start, resource_size(res));
+ if (fh_sadc_obj.regs == NULL) {
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+#endif
+ strncpy(fh_sadc_obj.isr_name, "sadc", sizeof("sadc"));
+ err = request_irq(fh_sadc_obj.irq_no, fh_sadc_isr, IRQF_NO_THREAD,
+ fh_sadc_obj.isr_name, &fh_sadc_obj);
+ if (err) {
+ dev_err(&pdev->dev, "request_irq:%d failed, %d\n", fh_sadc_obj.irq_no, err);
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+
+ init_completion(&fh_sadc_obj.done);
+ init_waitqueue_head(&fh_sadc_obj.readqueue);
+ mutex_init(&fh_sadc_obj.sadc_lock);
+ fh_sadc_obj.active_channel_no = 0;
+
+
+ err = misc_register(&fh_sadc_misc);
+
+ if (err < 0) {
+ pr_err("%s: ERROR: %s registration failed", __func__,
+ FH_SADC_MISC_DEVICE_NAME);
+ err = -ENXIO;
+ goto misc_error;
+ }
+ fh_sadc_obj.proc_file = proc_create(FH_SADC_PROC_FILE,
+ S_IRUGO, NULL, &fh_sadc_proc_ops);
+
+ if (!fh_sadc_obj.proc_file)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, "SADC");
+
+ pr_info("SADC probe successful, IO base addr: %p\n",
+ fh_sadc_obj.regs);
+ return 0;
+
+misc_error:
+ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj);
+
+fail_no_ioremap:
+ iounmap(fh_sadc_obj.regs);
+
+ return err;
+}
+
+static int __exit fh_sadc_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ if (fh_sadc_obj.clk) {
+ clk_disable_unprepare(fh_sadc_obj.clk);
+ clk_put(fh_sadc_obj.clk);
+ }
+ misc_deregister(&fh_sadc_misc);
+ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj);
+ proc_remove(fh_sadc_obj.proc_file);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+ iounmap(fh_sadc_obj.regs);
+
+ return 0;
+}
+
+
+static int fh_sadc_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_sadc_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+static int fh_sadc_read(struct file *filp, char __user *buf,
+ size_t len, loff_t *off)
+{
+ int ret;
+ struct sadc_info sadc_data;
+
+ ret = copy_from_user((void *) &sadc_data,
+ (void __user *) buf, sizeof(struct sadc_info));
+
+ spin_lock_irq(&fh_sadc_obj.lock);
+ g_sadc_data[sadc_data.channel].usrdata.channel = sadc_data.channel;
+ g_sadc_data[sadc_data.channel].flag = 1;
+ spin_unlock_irq(&fh_sadc_obj.lock);
+
+ /* wait for enough data*/
+ if (!wait_event_timeout(fh_sadc_obj.readqueue,
+ !g_sadc_data[sadc_data.channel].flag, 100)) {
+ pr_err("%s: channel:%d read time out\n",
+ __func__, sadc_data.channel);
+ return -1;
+ }
+ spin_lock_irq(&fh_sadc_obj.lock);
+ ret = copy_to_user((void __user *)buf,
+ (void *)&g_sadc_data[sadc_data.channel].usrdata,
+ sizeof(struct sadc_info));
+ spin_unlock_irq(&fh_sadc_obj.lock);
+ return len;
+}
+
+static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg) {
+
+ u32 ad_data;
+ u32 control_reg;
+ u16 ad_raw_data;
+ struct sadc_info sadc_info;
+ struct sadc_continue_cfg sadc_continue_cfg;
+#ifdef CONFIG_FH_SADC_V21
+ struct sadc_hit_data_cfg sadc_hit_data_cfg;
+#endif
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ mutex_lock(&sadc->sadc_lock);
+ switch (cmd) {
+ case IOCTL_GET_SINGLE_SADC_DATA:
+ {
+ if (copy_from_user((void *) &sadc_info, (void __user *) arg,
+ sizeof(sadc_info))) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EFAULT;
+ }
+ if ((wrap_readl(sadc, sadc_status2) & 0x10)) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EBUSY;
+ }
+ fh_sadc_mode_set(0);
+
+ fh_sadc_isr_read_data(&fh_sadc_obj, sadc_info.channel,\
+ &ad_raw_data);
+ ad_data = ad_raw_data * fh_sadc_obj.refvol;
+ ad_data /= fh_sadc_obj.activebit;
+ sadc_info.sadc_data = ad_data;
+ if (put_user(sadc_info.sadc_data,
+ (int __user *)(&((struct sadc_info *)arg)\
+ ->sadc_data))) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EFAULT;
+ }
+ break;
+ }
+ case IOCTL_SADC_POWER_DOWN:
+ control_reg = wrap_readl(sadc, sadc_control);
+ control_reg &= ~(1 << 12);
+ wrap_writel(sadc, sadc_control, control_reg);
+ break;
+ case IOCTL_CONTINUE_SADC_CFG:
+ {
+ if (copy_from_user((void *) &sadc_continue_cfg,
+ (void __user *) arg, sizeof(sadc_continue_cfg))) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EFAULT;
+ }
+ /*config continue model*/
+ fh_sadc_mode_set(1);
+
+ /*config channel cfg */
+ control_reg = wrap_readl(sadc, sadc_chn_cfg);
+ control_reg |= (sadc_continue_cfg.channel_cfg & 0x7ffffff);
+ wrap_writel(sadc, sadc_chn_cfg, control_reg);
+
+ /*config continue time */
+ fh_sadc_set_continuous_time(sadc_continue_cfg.continue_time);
+
+ fh_sadc_glitch_en_set(1);
+
+ /*config glitch time */
+ fh_sadc_set_glitch_time(sadc_continue_cfg.glitch_time);
+
+ /*config scan delta */
+ fh_sadc_scan_delta(sadc_continue_cfg.glitch_value);
+
+ /*config zero value */
+ fh_sadc_set_zero_value(sadc_continue_cfg.zero_value);
+
+ /*config precision*/
+ if (sadc_continue_cfg.precision)
+ fh_sadc_set_act_bit(sadc_continue_cfg.precision);
+
+ /*config eq flag*/
+ fh_sadc_cons_ch_eq_set(sadc_continue_cfg.eq_flag);
+
+ /*default config*/
+ fh_sadc_default_config();
+
+ /*glitch isr enable*/
+ wrap_writel(sadc, sadc_ier, 1<<16);
+ break;
+ }
+ case IOCTL_CONTINUE_SADC_START:
+ fh_sadc_scan_start();
+ break;
+ case IOCTL_CONTINUE_SADC_END:
+ fh_sadc_scan_end();
+ break;
+#ifdef CONFIG_FH_SADC_V21
+ case IOCTL_HIT_SADC_CFG:
+ if (copy_from_user((void *) &sadc_hit_data_cfg,
+ (void __user *) arg, sizeof(sadc_hit_data_cfg))) {
+ mutex_unlock(&sadc->sadc_lock);
+ return -EFAULT;
+ }
+ fh_sadc_hit_data_config(&sadc_hit_data_cfg);
+ break;
+#endif
+ }
+ mutex_unlock(&sadc->sadc_lock);
+ return 0;
+}
+
+
+/*******************
+ *
+ *
+ *add platform cause of i need the board info...
+ *in the probe function. i will register the sadc
+ *misc drive...then the app can open the sadc misc device..
+ *
+ ******************/
+static struct platform_driver fh_sadc_driver = {
+ .driver = {
+ .name = FH_SADC_PLAT_DEVICE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = fh_sadc_of_match,
+ },
+ .probe = fh_sadc_probe,
+ .remove = __exit_p(fh_sadc_remove),
+};
+
+
+
+static int __init fh_sadc_init(void)
+{
+ return platform_driver_register(&fh_sadc_driver);
+}
+
+static void __exit fh_sadc_exit(void)
+{
+
+ platform_driver_unregister(&fh_sadc_driver);
+
+}
+
+module_init(fh_sadc_init);
+module_exit(fh_sadc_exit);
+
+MODULE_DESCRIPTION("fullhan sadc device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("tangyh@fullhan.com");
+MODULE_ALIAS("platform:FH_sadc");
diff --git a/drivers/misc/fh_sadc_v2.h b/drivers/misc/fh_sadc_v2.h
new file mode 100644
index 00000000..d30d8e26
--- /dev/null
+++ b/drivers/misc/fh_sadc_v2.h
@@ -0,0 +1,105 @@
+/*
+ * fh_sadc.h
+ *
+ * Created on: Mar 13, 2015
+ * Author: duobao
+ */
+
+#ifndef FH_SADC_H_
+#define FH_SADC_H_
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/bug.h>
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+
+/****************************************************************************
+ * #define section
+ * add constant #define here if any
+ ***************************************************************************/
+#define FH_SADC_PROC_FILE "driver/sadc"
+#define MAX_CHANNEL_NO (8)
+#define LOOP_MODE (0x55)
+#define ISR_MODE (0xAA)
+
+
+#define SADC_TIMEOUT 0x55
+/****************************************************************************
+ * ADT section
+ * add Abstract Data Type definition here
+ ***************************************************************************/
+
+struct wrap_sadc_reg {
+ u32 sadc_model;
+ u32 sadc_cmd;
+ u32 sadc_control;
+ u32 sadc_scan_en;
+ u32 sadc_chn_cfg;
+ u32 sadc_chn_cfg1;
+ u32 sadc_glitch_cfg;
+ u32 sadc_continuous_time;
+ u32 sadc_glitch_time;
+ u32 sadc_ier;
+ u32 sadc_int_status;
+ u32 sadc_dout0;
+ u32 sadc_dout1;
+ u32 sadc_dout2;
+ u32 sadc_dout3;
+ u32 sadc_dout0_all;
+ u32 sadc_dout1_all;
+ u32 sadc_dout2_all;
+ u32 sadc_dout3_all;
+ u32 sadc_debuge0;
+ u32 sadc_status;
+ u32 sadc_cnt;
+ u32 sadc_timeout;
+ u32 sadc_status2;
+#ifdef CONFIG_FH_SADC_V21
+ u32 sadc_hit_value0;
+ u32 sadc_hit_value1;
+ u32 sadc_hit_value2;
+ u32 sadc_hit_value3;
+ u32 sadc_hit_cfg;
+ u32 sadc_hit_data0;
+ u32 sadc_hit_data1;
+ u32 sadc_hit_data2;
+ u32 sadc_hit_data3;
+#endif
+};
+
+
+struct wrap_sadc_obj {
+ void *regs;
+ u32 irq_no;
+ u32 active_channel_no;
+ u32 active_channel_status;
+ uint16_t channel_data[MAX_CHANNEL_NO];
+ u32 error_rec;
+ u32 en_isr;
+ u32 sample_mode;
+ spinlock_t lock;
+ struct mutex sadc_lock;
+ struct completion done;
+ struct proc_dir_entry *proc_file;
+ wait_queue_head_t readqueue;
+ u32 activebit;
+ u32 refvol;
+ struct clk *clk;
+ char isr_name[10];
+};
+
+long fh_sadc_get_value(int channel);
+
+
+#endif /* fh_SADC_H_ */
diff --git a/drivers/misc/fh_sadc_v3.c b/drivers/misc/fh_sadc_v3.c
new file mode 100644
index 00000000..a5dcd4c6
--- /dev/null
+++ b/drivers/misc/fh_sadc_v3.c
@@ -0,0 +1,975 @@
+
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include "fh_sadc_v3.h"
+#include <mach/pmu.h>
+#include <linux/sched.h>
+#include <linux/freezer.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <mach/clock.h>
+#include <mach/fh_sadc_plat.h>
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+#define wrap_readl(wrap, offset) \
+ __raw_readl(wrap->regs + offset)
+
+#define wrap_writel(wrap, offset, val) \
+ __raw_writel((val), wrap->regs + offset)
+
+
+#define IOCTL_GET_SADC_DATA 0x3
+#define IOCTL_GET_SINGLE_SADC_DATA 0x1
+#define IOCTL_GET_HIT_DATA 0x6
+#define IOCTL_SADC_POWER_DOWN 0xff
+
+#define FH_SADC_MISC_DEVICE_NAME "fh_sadc"
+static DECLARE_WAIT_QUEUE_HEAD(fh_sadc_hit_wait);
+
+
+/****************************************************************************
+* ADT section
+* add definition of user defined Data Type that only be used in this file here
+***************************************************************************/
+struct sadc_info {
+ int channel;
+ int sadc_data;
+};
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc,\
+ u32 channel, u16 *buf);
+static int fh_sadc_open(struct inode *inode, struct file *file);
+static int fh_sadc_release(struct inode *inode, struct file *filp);
+static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,\
+ unsigned long arg);
+
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+static struct wrap_sadc_obj fh_sadc_obj;
+
+static const struct file_operations fh_sadc_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_sadc_open,
+ .release = fh_sadc_release,
+ .unlocked_ioctl = fh_sadc_ioctl,
+};
+
+static struct miscdevice fh_sadc_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = FH_SADC_MISC_DEVICE_NAME,
+ .fops = &fh_sadc_fops,
+};
+
+/*****************************************************************************
+ *
+ *
+ * function body
+ *
+ *
+ *****************************************************************************/
+int fh_sadc_enable(void)
+{
+ u32 control_reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ control_reg = wrap_readl(sadc, SADC_CTRL0);
+ control_reg |= 1 << 0;
+ wrap_writel(sadc, SADC_CTRL0, control_reg);
+ return 0;
+}
+
+int fh_sadc_disable(void)
+{
+ u32 control_reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ control_reg = wrap_readl(sadc, SADC_CTRL0);
+ control_reg &= ~(1 << 0);
+ wrap_writel(sadc, SADC_CTRL0, control_reg);
+ return 0;
+}
+
+int fh_sadc_update(void)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, SADC_CTRL1);
+ reg |= 1;
+ wrap_writel(sadc, SADC_CTRL1, reg);
+ return 0;
+}
+
+int fh_sadc_lowpwr_enable(void)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, SADC_CTRL2);
+ reg |= (1 << 0);
+ wrap_writel(sadc, SADC_CTRL2, reg);
+ return 0;
+}
+
+u32 fh_sadc_lowpwr_disable(void)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ reg = wrap_readl(sadc, SADC_CTRL2);
+ reg &= (~(1 << 0));
+ wrap_writel(sadc, SADC_CTRL2, reg);
+ return 0;
+}
+
+int fh_sadc_continue_enable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG1);
+ reg |= (1 << channel);
+ wrap_writel(sadc, SADC_CONFIG1, reg);
+ return 0;
+}
+
+int fh_sadc_continue_disable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG1);
+ reg &= (~(1 << channel));
+ wrap_writel(sadc, SADC_CONFIG1, reg);
+ return 0;
+}
+
+int fh_sadc_single_enable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG0);
+ reg |= (1 << channel);
+ wrap_writel(sadc, SADC_CONFIG0, reg);
+ return 0;
+}
+
+int fh_sadc_single_disable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG0);
+ reg &= (~(1 << channel));
+ wrap_writel(sadc, SADC_CONFIG0, reg);
+ return 0;
+}
+
+int fh_sadc_eq_enable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG2);
+ reg |= (1 << channel);
+ wrap_writel(sadc, SADC_CONFIG2, reg);
+ return 0;
+}
+
+int fh_sadc_eq_disable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG2);
+ reg &= (~(1 << channel));
+ wrap_writel(sadc, SADC_CONFIG2, reg);
+ return 0;
+}
+
+int fh_sadc_hit_enable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG3);
+ reg |= (1 << channel);
+ wrap_writel(sadc, SADC_CONFIG3, reg);
+ return 0;
+}
+
+int fh_sadc_hit_disable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel >= MAX_CHANNEL_NO) {
+ pr_err("sadc channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG3);
+ reg &= (~(1 << channel));
+ wrap_writel(sadc, SADC_CONFIG3, reg);
+ return 0;
+}
+
+int fh_sadc_scan_time(u32 scan_time)
+{
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 value;
+
+ value = scan_time*(sadc->frequency/1000);
+ wrap_writel(sadc, SADC_CONFIG4, value);
+ return 0;
+}
+
+int fh_sadc_glitch_time(u32 glitch_time)
+{
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 value;
+
+ value = glitch_time*(sadc->frequency/1000);
+ wrap_writel(sadc, SADC_CONFIG5, value);
+ return 0;
+}
+
+int fh_sadc_noise_range(u32 noise_range)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 value;
+
+ value = (noise_range*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value &= 0xfff;
+ if(value >= 0xff) {
+ pr_err("sadc noise range error %d\n", noise_range);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_CONFIG6);
+ reg &= (~(0xff << 0));
+ reg |= (value << 0);
+ wrap_writel(sadc, SADC_CONFIG6, reg);
+ return 0;
+}
+
+int fh_sadc_zero_value(u32 zero_value)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+ u32 value;
+
+ value = (zero_value*fh_sadc_obj.activebit)/fh_sadc_obj.refvol;
+ value &= 0xfff;
+
+ reg = wrap_readl(sadc, SADC_CONFIG6);
+ reg &= (~(0xfff << 16));
+ reg |= (value << 16);
+ wrap_writel(sadc, SADC_CONFIG6, reg);
+ return 0;
+}
+
+int fh_sadc_active_bit(u32 active_bit)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(active_bit > 0x12) {
+ pr_err("sadc active bit error %d\n", active_bit);
+ return -1;
+ }
+ reg = 0xfff >> (12-active_bit);
+ reg = reg << (12-active_bit);
+ wrap_writel(sadc, SADC_CONFIG7, reg);
+ return 0;
+}
+
+int fh_sadc_int_enable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel > MAX_CHANNEL_NO) {
+ pr_err("sadc channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_INT_EN);
+ reg |= (1 << channel);
+ wrap_writel(sadc, SADC_INT_EN, reg);
+ return 0;
+}
+
+int fh_sadc_int_disable(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel > MAX_CHANNEL_NO) {
+ pr_err("sadc channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_INT_EN);
+ reg &= (~(1 << channel));
+ wrap_writel(sadc, SADC_INT_EN, reg);
+ return 0;
+}
+
+int fh_sadc_press_int_en(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel > MAX_CHANNEL_NO) {
+ pr_err("sadc channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_INT_EN);
+ reg |= (1 << (channel + 8));
+ wrap_writel(sadc, SADC_INT_EN, reg);
+ return 0;
+}
+
+int fh_sadc_press_int_dis(u32 channel)
+{
+ u32 reg;
+ struct wrap_sadc_obj *sadc = &fh_sadc_obj;
+
+ if(channel > MAX_CHANNEL_NO) {
+ pr_err("sadc channel num error %d\n", channel);
+ return -1;
+ }
+ reg = wrap_readl(sadc, SADC_INT_EN);
+ reg &= (~(1 << (channel + 8)));
+ wrap_writel(sadc, SADC_INT_EN, reg);
+ return 0;
+}
+
+u32 fh_sadc_isr_read_data(struct wrap_sadc_obj *sadc, u32 channel,
+ u16 *buf) {
+ u32 ret_time;
+
+ reinit_completion(&sadc->done);
+ sadc->active_channel_no = 0xffffffff;
+ fh_sadc_eq_enable(channel);
+ fh_sadc_active_bit(12);
+ fh_sadc_continue_enable(channel);
+ fh_sadc_int_enable(channel);
+ /*10ms*/
+ fh_sadc_scan_time(10);
+ fh_sadc_enable();
+ fh_sadc_update();
+ ret_time = wait_for_completion_timeout(&sadc->done, 500);
+ if (ret_time == 0) {
+ printk(KERN_ERR "sadc timeout..\n");
+ return 1;
+ }
+
+ if(channel == sadc->active_channel_no)
+ *buf = (sadc->channel_data[channel]*fh_sadc_obj.refvol)
+ /fh_sadc_obj.activebit;
+ else
+ pr_err("sadc channel :%d,return channel:%d error\n", channel,
+ sadc->active_channel_no);
+ fh_sadc_eq_disable(channel);
+ fh_sadc_continue_disable(channel);
+ fh_sadc_int_disable(channel);
+ fh_sadc_update();
+ return 0;
+}
+
+u32 fh_sadc_isr_read_single_data(struct wrap_sadc_obj *sadc, u32 channel,
+ u16 *buf) {
+ u32 ret_time;
+
+ reinit_completion(&sadc->done);
+ sadc->active_channel_no = 0xffffffff;
+ fh_sadc_active_bit(12);
+ fh_sadc_single_enable(channel);
+ fh_sadc_int_enable(channel);
+ /*10ms*/
+ fh_sadc_scan_time(10);
+ fh_sadc_enable();
+ fh_sadc_update();
+ ret_time = wait_for_completion_timeout(&sadc->done, 500);
+ if (ret_time == 0) {
+ printk(KERN_ERR "sadc timeout..\n");
+ return 1;
+ }
+ if(channel == sadc->active_channel_no)
+ *buf = (sadc->channel_data[channel]*fh_sadc_obj.refvol)
+ /fh_sadc_obj.activebit;
+ else
+ pr_err("sadc channel :%d,return channel:%d error\n", channel,
+ sadc->active_channel_no);
+ fh_sadc_single_disable(channel);
+ fh_sadc_int_disable(channel);
+ fh_sadc_update();
+ return 0;
+}
+
+u32 fh_sadc_isr_read_hit_data(struct wrap_sadc_obj *sadc, u32 channel,
+ u16 *buf) {
+
+ sadc->active_channel_no = 0xffffffff;
+ fh_sadc_active_bit(12);
+ fh_sadc_continue_enable(channel);
+ fh_sadc_hit_enable(channel);
+ fh_sadc_press_int_en(channel);
+ /*10ms*/
+ fh_sadc_scan_time(10);
+ fh_sadc_enable();
+ fh_sadc_update();
+ wait_event_freezable(fh_sadc_hit_wait, channel == sadc->active_channel_no);
+ *buf = (sadc->channel_data[channel]*fh_sadc_obj.refvol)
+ / fh_sadc_obj.activebit;
+ fh_sadc_continue_disable(channel);
+ fh_sadc_hit_disable(channel);
+ fh_sadc_press_int_dis(channel);
+ fh_sadc_update();
+ return 0;
+}
+
+static irqreturn_t fh_sadc_isr(int irq, void *dev_id)
+{
+
+ u32 isr_status;
+ u32 isr_active;
+ u32 isr_en;
+ u32 temp_data = 0;
+ u32 channel = 0;
+ u32 data = 0;
+ struct wrap_sadc_obj *sadc = (struct wrap_sadc_obj *) dev_id;
+
+ isr_status = wrap_readl(sadc, SADC_INT_STA);
+ isr_en = wrap_readl(sadc, SADC_INT_EN);
+ isr_active = isr_status & isr_en;
+ if (isr_active & 0xff) {
+ channel = ffs(isr_active);
+ channel = channel - 1;
+ switch (channel/2) {
+ case 0:
+ /*read channel 0 1*/
+ temp_data = wrap_readl(sadc, SADC_DOUT0);
+ break;
+ case 1:
+ /*read channel 2 3*/
+ temp_data = wrap_readl(sadc, SADC_DOUT1);
+ break;
+ case 2:
+ /*read channel 4 5*/
+ temp_data = wrap_readl(sadc, SADC_DOUT2);
+ break;
+ case 3:
+ /*read channel 6 7*/
+ temp_data = wrap_readl(sadc, SADC_DOUT3);
+ break;
+ default:
+ break;
+ }
+ complete(&(sadc->done));
+ } else if (isr_active & 0xffff00) {
+ if(isr_active & 0xff00)
+ channel = ffs(isr_active >> 8);
+ else
+ channel = ffs(isr_active >> 16);
+ channel = channel - 1;
+ switch (channel/2) {
+ case 0:
+ /*read channel 0 1*/
+ temp_data = wrap_readl(sadc, SADC_BUTTON_DOUT0);
+ break;
+ case 1:
+ /*read channel 2 3*/
+ temp_data = wrap_readl(sadc, SADC_BUTTON_DOUT1);
+ break;
+ case 2:
+ /*read channel 4 5*/
+ temp_data = wrap_readl(sadc, SADC_BUTTON_DOUT2);
+ break;
+ case 3:
+ /*read channel 6 7*/
+ temp_data = wrap_readl(sadc, SADC_BUTTON_DOUT3);
+ break;
+ default:
+ break;
+ }
+ wake_up(&fh_sadc_hit_wait);
+ }
+
+ if (channel % 2)
+ /*read high 16bit*/
+ data = (temp_data >> 16) & 0xfff;
+ else
+ /*read low 16bit*/
+ data = (temp_data & 0xfff);
+ sadc->channel_data[channel] = data;
+ sadc->active_channel_no = channel;
+ wrap_writel(sadc, SADC_INT_STA, (~isr_status));
+ return IRQ_HANDLED;
+}
+
+long fh_sadc_get_value(int channel)
+{
+ unsigned int ret;
+ long w = 0;
+ u16 ad_raw_data;
+
+ if (channel < 0) {
+ printk(KERN_ERR "ERROR: %s, sadc channel no %d is incorrect\n",
+ __func__, channel);
+ return 0;
+ }
+
+ fh_sadc_enable();
+
+ ret = fh_sadc_isr_read_data(&fh_sadc_obj, channel, &ad_raw_data);
+
+ if (ret != 0) {
+ printk(KERN_INFO "sadc error code:0x%x\n", ret);
+ } else {
+ w = ad_raw_data * fh_sadc_obj.refvol / fh_sadc_obj.activebit;
+ printk(KERN_INFO "the value of sadc is: %ld\n", w);
+ }
+
+ return w;
+}
+
+static void del_char(char *str, char ch)
+{
+ char *p = str;
+ char *q = str;
+ while (*q) {
+ if (*q != ch)
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+}
+
+static ssize_t fh_sadc_proc_write(struct file *filp, const char *buf,
+ size_t len, loff_t *off)
+{
+ char message[32] = {0};
+ char * const delim = ",";
+ char *cur = message;
+ int i;
+ char *param_str[2];
+ int ret;
+ unsigned long param = 0;
+ len = (len > 32) ? 32 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for (i = 0; i < 2; i++) {
+ param_str[i] = strsep(&cur, delim);
+ if (!param_str[i]) {
+ pr_err("%s: ERROR: parameter[%d] is empty\n",
+ __func__, i);
+ pr_err("[debug],[channel],[pwr_down]\n");
+ return -EINVAL;
+ } else {
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ }
+ }
+
+ if (!strcmp(param_str[0], "pwr_down")) {
+ ret = (u32)kstrtoul(param_str[1], 10, &param);
+ param ? fh_sadc_lowpwr_enable() : fh_sadc_lowpwr_disable();
+ }
+
+ return len;
+}
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+ counter = 0;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int i;
+ u32 ret;
+ u16 ad_raw_data;
+
+ seq_printf(sfile, "\nSADC Status:\n");
+ for (i = 0; i < 8; i++) {
+ ret = fh_sadc_isr_read_data(&fh_sadc_obj, i, &ad_raw_data);
+ if (ret != 0)
+ seq_printf(sfile, "contine sadc error code:0x%x\n", ret);
+ else
+ seq_printf(sfile, "continue read channel: %d \tvalue: %u\n", i,
+ ad_raw_data);
+ }
+ return 0;
+}
+
+static const struct seq_operations isp_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_sadc_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &isp_seq_ops);
+}
+
+static const struct file_operations fh_sadc_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_sadc_proc_open,
+ .read = seq_read,
+ .write = fh_sadc_proc_write,
+ .release = seq_release,
+};
+static struct of_device_id const fh_sadc_of_match[] = {
+ { .compatible = "fh,fh-sadc" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fh_sadc_of_match);
+static int fh_sadc_probe(struct platform_device *pdev)
+{
+ int err;
+#ifdef CONFIG_USE_OF
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *res;
+ struct fh_sadc_platform_data *plat_data;
+#endif
+ struct clk *sadc_clk;
+ int irq;
+
+ sadc_clk = clk_get(&pdev->dev, "sadc_clk");
+ if (IS_ERR(sadc_clk)) {
+ err = PTR_ERR(sadc_clk);
+ return -EPERM;
+ }
+ clk_prepare_enable(sadc_clk);
+ fh_sadc_obj.clk = sadc_clk;
+#ifdef CONFIG_FPGA
+#define FPGA_SADC_CLOCK 15000000
+ fh_sadc_obj.frequency = FPGA_SADC_CLOCK;
+#else
+ fh_sadc_obj.frequency = clk_get_rate(sadc_clk);
+#endif
+#ifdef CONFIG_USE_OF
+ match = of_match_device(fh_sadc_of_match, &pdev->dev);
+ if (!match) {
+ pr_info("Failed to find sadc controller\n");
+ return -ENODEV;
+ }
+
+ fh_sadc_obj.regs = of_iomap(np, 0);
+ if (fh_sadc_obj.regs == NULL) {
+ err = -ENXIO;
+ return err;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ goto fail_no_ioremap;
+ }
+ of_property_read_u32(np, "ref-vol", &fh_sadc_obj.refvol);
+ of_property_read_u32(np, "active-bit", &fh_sadc_obj.activebit);
+#else
+ plat_data = pdev->dev.platform_data;
+ if (!plat_data) {
+ dev_err(&pdev->dev, "sadc get platform data error..\n");
+ return -ENODEV;
+ }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "sadc get platform source error..\n");
+ return -ENODEV;
+ }
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "sadc region already claimed\n");
+ return -EBUSY;
+ }
+ fh_sadc_obj.refvol = plat_data->ref_vol;
+ fh_sadc_obj.activebit = plat_data->active_bit;
+ fh_sadc_obj.regs = ioremap(res->start, resource_size(res));
+ if (fh_sadc_obj.regs == NULL) {
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+ irq = platform_get_irq(pdev, 0);
+ irq = irq_create_mapping(NULL, irq);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no IRQ defined!\n");
+ goto fail_no_ioremap;
+ }
+#endif
+
+ fh_sadc_obj.irq_no = irq;
+ init_completion(&fh_sadc_obj.done);
+ mutex_init(&fh_sadc_obj.sadc_lock);
+ fh_sadc_obj.active_channel_no = 0xffffffff;
+ strncpy(fh_sadc_obj.isr_name, "sadc", sizeof("sadc"));
+ err = request_irq(fh_sadc_obj.irq_no, fh_sadc_isr, 0,
+ fh_sadc_obj.isr_name,
+ &fh_sadc_obj);
+ if (err) {
+ dev_dbg(&pdev->dev, "request_irq failed, %d\n", err);
+ err = -ENXIO;
+ goto err_irq;
+ }
+
+ err = misc_register(&fh_sadc_misc);
+
+ if (err < 0) {
+ pr_err("%s: ERROR: %s registration failed", __func__,
+ FH_SADC_MISC_DEVICE_NAME);
+ err = -ENXIO;
+ goto misc_error;
+ }
+
+ fh_sadc_obj.proc_file = proc_create(FH_SADC_PROC_FILE,
+ S_IRUGO, NULL, &fh_sadc_proc_ops);
+
+ if (!fh_sadc_obj.proc_file)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, "SADC");
+
+ return 0;
+
+misc_error:
+ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj);
+
+err_irq:
+ iounmap(fh_sadc_obj.regs);
+
+fail_no_ioremap:
+#ifndef CONFIG_USE_OF
+ release_mem_region(res->start, resource_size(res));
+#endif
+ return err;
+}
+
+static int __exit fh_sadc_remove(struct platform_device *pdev)
+{
+
+ struct resource *res;
+
+ if (fh_sadc_obj.clk) {
+ clk_disable_unprepare(fh_sadc_obj.clk);
+ clk_put(fh_sadc_obj.clk);
+ }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ misc_deregister(&fh_sadc_misc);
+ proc_remove(fh_sadc_obj.proc_file);
+ free_irq(fh_sadc_obj.irq_no, &fh_sadc_obj);
+ iounmap(fh_sadc_obj.regs);
+ release_mem_region(res->start, resource_size(res));
+ return 0;
+
+}
+
+
+static int fh_sadc_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_sadc_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static long fh_sadc_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg) {
+ u16 ad_raw_data;
+ struct sadc_info sadc_info;
+ switch (cmd) {
+ case IOCTL_GET_SADC_DATA:
+ {
+ mutex_lock(&fh_sadc_obj.sadc_lock);
+ if (copy_from_user((void *) &sadc_info, (void __user*) arg,
+ sizeof(sadc_info))) {
+ mutex_unlock(&fh_sadc_obj.sadc_lock);
+ return -EFAULT;
+ }
+
+ fh_sadc_isr_read_data(&fh_sadc_obj, sadc_info.channel,\
+ &ad_raw_data);
+ sadc_info.sadc_data = ad_raw_data;
+ if (put_user(sadc_info.sadc_data,
+ (int __user *)(&((struct sadc_info *)arg)\
+ ->sadc_data))) {
+ mutex_unlock(&fh_sadc_obj.sadc_lock);
+ return -EFAULT;
+ }
+ mutex_unlock(&fh_sadc_obj.sadc_lock);
+ break;
+ }
+ case IOCTL_GET_SINGLE_SADC_DATA:
+ {
+ mutex_lock(&fh_sadc_obj.sadc_lock);
+ if (copy_from_user((void *) &sadc_info, (void __user *) arg,
+ sizeof(sadc_info))) {
+ mutex_unlock(&fh_sadc_obj.sadc_lock);
+ return -EFAULT;
+ }
+
+ fh_sadc_isr_read_single_data(&fh_sadc_obj, sadc_info.channel,\
+ &ad_raw_data);
+ sadc_info.sadc_data = ad_raw_data;
+ if (put_user(sadc_info.sadc_data,
+ (int __user *)(&((struct sadc_info *)arg)\
+ ->sadc_data))) {
+ mutex_unlock(&fh_sadc_obj.sadc_lock);
+ return -EFAULT;
+ }
+ mutex_unlock(&fh_sadc_obj.sadc_lock);
+ break;
+ }
+ case IOCTL_GET_HIT_DATA:
+ {
+ if (copy_from_user((void *) &sadc_info, (void __user*) arg,
+ sizeof(sadc_info))) {
+ return -EFAULT;
+ }
+
+ fh_sadc_isr_read_hit_data(&fh_sadc_obj, sadc_info.channel,\
+ &ad_raw_data);
+ sadc_info.sadc_data = ad_raw_data;
+ if (put_user(sadc_info.sadc_data,
+ (int __user *)(&((struct sadc_info *)arg)\
+ ->sadc_data))) {
+ return -EFAULT;
+ }
+ break;
+ }
+ case IOCTL_SADC_POWER_DOWN:
+ fh_sadc_lowpwr_enable();
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+/*******************
+ *
+ *
+ *add platform cause of i need the board info...
+ *in the probe function. i will register the sadc
+ *misc drive...then the app can open the sadc misc device..
+ *
+ ******************/
+static struct platform_driver fh_sadc_driver = {
+ .driver = {
+ .name = "fh_sadc",
+ .owner = THIS_MODULE,
+ .of_match_table = fh_sadc_of_match,
+ },
+ .probe = fh_sadc_probe,
+ .remove = __exit_p(fh_sadc_remove),
+};
+
+
+
+static int __init fh_sadc_init(void)
+{
+ return platform_driver_register(&fh_sadc_driver);
+}
+
+static void __exit fh_sadc_exit(void)
+{
+
+ platform_driver_unregister(&fh_sadc_driver);
+
+}
+
+module_init(fh_sadc_init);
+module_exit(fh_sadc_exit);
+
+MODULE_DESCRIPTION("fullhan sadc device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("tangyh@fullhan.com");
+MODULE_ALIAS("platform:FH_sadc");
diff --git a/drivers/misc/fh_sadc_v3.h b/drivers/misc/fh_sadc_v3.h
new file mode 100644
index 00000000..a79dee14
--- /dev/null
+++ b/drivers/misc/fh_sadc_v3.h
@@ -0,0 +1,83 @@
+/*
+ * fh_sadc.h
+ *
+ * Created on: Mar 13, 2015
+ * Author: duobao
+ */
+
+#ifndef FH_SADC_V3_H_
+#define FH_SADC_V3_H_
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/bug.h>
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+
+/****************************************************************************
+ * #define section
+ * add constant #define here if any
+ ***************************************************************************/
+#define FH_SADC_PROC_FILE "driver/sadc"
+#define MAX_CHANNEL_NO (8)
+
+#define SADC_CTRL0 0x0
+#define SADC_CTRL1 0x4
+#define SADC_CTRL2 0x8
+#define SADC_CONFIG0 0x10
+#define SADC_CONFIG1 0x14
+#define SADC_CONFIG2 0x18
+#define SADC_CONFIG3 0x1c
+#define SADC_CONFIG4 0x20
+#define SADC_CONFIG5 0x24
+#define SADC_CONFIG6 0x28
+#define SADC_CONFIG7 0x2c
+#define SADC_INT_EN 0x40
+#define SADC_INT_STA 0x44
+#define SADC_DOUT0 0x50
+#define SADC_DOUT1 0x54
+#define SADC_DOUT2 0x58
+#define SADC_DOUT3 0x5c
+#define SADC_BUTTON_DOUT0 0x60
+#define SADC_BUTTON_DOUT1 0x64
+#define SADC_BUTTON_DOUT2 0x68
+#define SADC_BUTTON_DOUT3 0x6c
+#define SADC_DEBUG0 0x100
+#define SADC_DEBUG1 0x104
+#define SADC_DEBUG2 0x108
+#define SADC_DEBUG3 0x10c
+#define SADC_DEBUG4 0x110
+#define SADC_DEBUG5 0x114
+#define SADC_DEBUG6 0x118
+#define SADC_ECO 0x120
+
+struct wrap_sadc_obj {
+ void *regs;
+ u32 irq_no;
+ u32 frequency;
+ u32 active_channel_no;
+ uint16_t channel_data[MAX_CHANNEL_NO];
+ spinlock_t lock;
+ struct mutex sadc_lock;
+ struct completion done;
+ struct proc_dir_entry *proc_file;
+ u32 activebit;
+ u32 refvol;
+ struct clk *clk;
+ char isr_name[10];
+};
+
+long fh_sadc_get_value(int channel);
+
+
+#endif /* fh_SADC_V3_H_ */
diff --git a/drivers/misc/fh_stepmotor.c b/drivers/misc/fh_stepmotor.c
new file mode 100644
index 00000000..74678a68
--- /dev/null
+++ b/drivers/misc/fh_stepmotor.c
@@ -0,0 +1,452 @@
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include <mach/pmu.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+
+#include "fh_stepmotor.h"
+
+#define FHSM_DEF_PERIOD (128)
+
+struct fh_sm_obj_t* fh_sm_obj[MAX_FHSM_NR];
+static int fh_stepmotor_probe(struct platform_device *pdev);
+static int __exit fh_stepmotor_remove(struct platform_device *pdev);
+
+
+
+
+
+
+
+
+static long fh_stepmotor_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ struct fh_sm_param* param;
+ struct fh_sm_lut* lut;
+ struct fh_sm_obj_t* curobj;
+ if (arg == 0)
+ return -EINVAL;
+
+ if (unlikely(_IOC_TYPE(cmd) != FH_SM_IOCTL_MAGIC))
+ {
+ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n",
+ __func__, _IOC_TYPE(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+ curobj = (struct fh_sm_obj_t*)filp->private_data;
+ if (curobj == NULL) {
+ return -EFAULT;
+ }
+ switch (cmd)
+ {
+ case FH_SM_SET_PARAM:
+ {
+ if (fh_stepmotor_is_busy(curobj)) {
+ ret = -EINVAL;
+ break;
+ }
+ param = kzalloc(sizeof(struct fh_sm_param), GFP_KERNEL);
+ if (param == NULL)
+ {
+ ret = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(param, (void __user *)arg, sizeof(struct fh_sm_param)))
+ {
+ ret = EINVAL;
+ kfree(param);
+ break;
+ }
+ fh_stepmotor_set_hw_param(curobj,param);
+ kfree(param);
+ ret = 0;
+ break;
+ }
+ case FH_SM_GET_PARAM:
+ {
+ param = kzalloc(sizeof(struct fh_sm_param), GFP_KERNEL);
+ if (param == NULL)
+ {
+ ret = -ENOMEM;
+ break;
+ }
+ fh_stepmotor_get_hw_param(curobj,param);
+ if (copy_to_user( (void __user *)arg, (void *)param,sizeof(struct fh_sm_param))) {
+ kfree(param);
+ return -EFAULT;
+ }
+ kfree(param);
+ ret = 0;
+ break;
+ }
+
+
+ case FH_SM_START_ASYNC:
+ {
+ int cycles = 0;
+ if (fh_stepmotor_is_busy(curobj)) {
+ ret = -EINVAL;
+ break;
+ }
+ if (copy_from_user(&cycles, (void __user *)arg, sizeof(int)))
+ {
+ ret = EINVAL;
+ break;
+ }
+
+ fh_stepmotor_start_async(curobj,cycles);
+ ret = 0;
+ break;
+ }
+ case FH_SM_START_SYNC:
+ {
+ int cycles = 0;
+ int fin = 0;
+ if (fh_stepmotor_is_busy(curobj)) {
+ ret = -EINVAL;
+ break;
+ }
+ if (copy_from_user(&cycles, (void __user *)arg, sizeof(int)))
+ {
+ ret = EINVAL;
+ break;
+ }
+
+ fin = fh_stepmotor_start_sync(curobj,cycles);
+ if (copy_to_user( (void __user *)arg, (void *)&fin,sizeof(fin))) {
+ return -EFAULT;
+ }
+ ret = 0;
+ break;
+ }
+ case FH_SM_STOP:
+ {
+ int fincnt = 0;
+ fincnt = fh_stepmotor_stop(curobj);
+ if (copy_to_user( (void __user *)arg, (void *)&fincnt,sizeof(fincnt))) {
+ return -EFAULT;
+ }
+ ret = 0;
+ break;
+ }
+ case FH_SM_GET_CUR_CYCLE:
+ {
+ int fincnt = 0;
+ fincnt = fh_stepmotor_get_current_cycle(curobj);
+ if (copy_to_user( (void __user *)arg, (void *)&fincnt,sizeof(fincnt))) {
+ return -EFAULT;
+ }
+ ret = 0;
+ break;
+ }
+
+ case FH_SM_GET_LUT:
+ {
+ struct fh_sm_lut tmplut;
+
+ lut = kzalloc(sizeof(struct fh_sm_lut), GFP_KERNEL);
+ if (lut == NULL)
+ {
+ ret = -ENOMEM;
+ break;
+ }
+ lut->lutsize = fh_stepmotor_get_lutsize(curobj);
+ lut->lut = kzalloc(lut->lutsize, GFP_KERNEL);
+ if (lut->lut == NULL) {
+ ret = EINVAL;
+ kfree(lut);
+ break;
+ }
+ fh_stepmotor_get_lut(curobj,lut);
+
+ if (copy_from_user(&tmplut, (void __user *)arg, sizeof(struct fh_sm_lut)))
+ {
+ ret = EINVAL;
+ kfree(lut->lut);
+ kfree(lut);
+ break;
+ }
+ if (tmplut.lutsize != 0 && tmplut.lut != NULL) {
+ if (copy_to_user( (void __user *)tmplut.lut,lut->lut, lut->lutsize))
+ {
+ ret = EINVAL;
+ kfree(lut->lut);
+ kfree(lut);
+ break;
+ }
+ kfree(lut->lut);
+ lut->lut = tmplut.lut;
+
+ if (copy_to_user(lut, (void __user *)arg, sizeof(struct fh_sm_lut)))
+ {
+ ret = EINVAL;
+ kfree(lut);
+ break;
+ }
+ } else {
+ kfree(lut->lut);
+ }
+
+ kfree(lut);
+ ret = 0;
+ break;
+ }
+ case FH_SM_SET_LUT:
+ {
+ if (fh_stepmotor_is_busy(curobj)) {
+ ret = -EINVAL;
+ break;
+ }
+ lut = kzalloc(sizeof(struct fh_sm_lut), GFP_KERNEL);
+ if (lut == NULL)
+ {
+ ret = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(lut, (void __user *)arg, sizeof(struct fh_sm_lut)))
+ {
+ ret = EINVAL;
+ break;
+ }
+ if (lut->lut != NULL) {
+ int* buff = kzalloc(lut->lutsize, GFP_KERNEL);
+ if (copy_from_user(buff, (void __user *)lut->lut, lut->lutsize)) {
+ kfree(buff);
+ ret = EINVAL;
+ lut->lut = NULL;
+ }
+ lut->lut = buff;
+ }
+
+ ret = fh_stepmotor_set_lut(curobj,lut);
+
+ if (lut->lut != NULL) {
+ kfree(lut->lut);
+ }
+ kfree(lut);
+ ret = 0;
+ break;
+ }
+ }
+
+
+
+
+ return ret;
+}
+
+static int fh_stepmotor_open(struct inode *inode, struct file *file)
+{
+ if (strchr(file->f_path.dentry->d_name.name,'0') != NULL) {
+ file->private_data = (void*)fh_sm_obj[0];
+ } else if(strchr(file->f_path.dentry->d_name.name,'1') != NULL) {
+ file->private_data = (void*)fh_sm_obj[1];
+ }
+ return 0;
+}
+
+static int fh_stepmotor_release(struct inode *inode, struct file *filp)
+{
+
+ return 0;
+}
+
+
+static const struct file_operations fh_stepmotor_fops =
+{
+ .owner = THIS_MODULE,
+ .open = fh_stepmotor_open,
+ .release = fh_stepmotor_release,
+ .unlocked_ioctl = fh_stepmotor_ioctl,
+};
+#if 0
+static struct miscdevice fh_stepmotor_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = FH_SM_MISC_DEVICE_NAME,
+ .fops = &fh_stepmotor_fops,
+};
+#endif
+struct miscdevice* fh_stepmotor_device[MAX_FHSM_NR];
+
+
+
+#ifdef CONFIG_USE_OF
+static struct of_device_id const fh_sm_of_match[] = {
+ { .compatible = "fh,fh-stm" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fh_sm_of_match);
+#endif
+static struct platform_driver fh_stepmotor_driver = {
+ .driver = {
+ .name = FH_SM_PLAT_DEVICE_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_USE_OF
+ .of_match_table = fh_sm_of_match,
+#endif
+ },
+ .probe = fh_stepmotor_probe,
+ .remove = __exit_p(fh_stepmotor_remove),
+};
+
+
+static int fh_stepmotor_probe(struct platform_device *pdev)
+{
+ int err;
+ struct clk *sm_clk;
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *res;
+#endif
+ int id = 0;
+ static char devstr[MAX_FHSM_NR][40];
+ char clkname[24] = {0};
+
+#ifdef CONFIG_USE_OF
+ id = of_alias_get_id(pdev->dev.of_node, "stm");
+ fh_sm_obj[id] = kzalloc(sizeof(struct fh_sm_obj_t),GFP_KERNEL);
+ if (fh_sm_obj[id] == NULL) {
+ err = -ENXIO;
+ return err;
+ }
+ fh_sm_obj[id]->irq_no = irq_of_parse_and_map(np, 0);
+ if (fh_sm_obj[id]->irq_no < 0) {
+ dev_warn(&pdev->dev, "sm interrupt is not available.\n");
+ return fh_sm_obj[id]->irq_no;
+ }
+
+ fh_sm_obj[id]->regs = of_iomap(np, 0);
+ if (fh_sm_obj[id]->regs == NULL) {
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+#else
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "sm get platform source error..\n");
+ return -ENODEV;
+ }
+ id = pdev->id;
+ fh_sm_obj[id] = kzalloc(sizeof(struct fh_sm_obj_t),GFP_KERNEL);
+ if (fh_sm_obj[id] == NULL) {
+ err = -ENXIO;
+ return err;
+ }
+ fh_sm_obj[id]->irq_no = platform_get_irq(pdev, 0);
+ fh_sm_obj[id]->irq_no = irq_create_mapping(NULL,
+ fh_sm_obj[id]->irq_no);
+ if (fh_sm_obj[id]->irq_no < 0) {
+ dev_warn(&pdev->dev, "sm interrupt is not available.\n");
+ return fh_sm_obj[id]->irq_no;
+ }
+
+ res = request_mem_region(res->start, resource_size(res),
+ pdev->name);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "sm region already claimed\n");
+ return -EBUSY;
+ }
+ fh_sm_obj[id]->regs = ioremap(res->start, resource_size(res));
+ if (fh_sm_obj[id]->regs == NULL) {
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+
+#endif
+ sprintf(clkname,"stm%d_clk",id);
+ snprintf(fh_sm_obj[id]->isrname, sizeof(fh_sm_obj[id]->isrname), "stm-%d", id);
+
+ sm_clk = clk_get(&pdev->dev, clkname);
+ if (!IS_ERR(sm_clk))
+ clk_prepare_enable(sm_clk);
+
+
+ init_completion(&fh_sm_obj[id]->run_complete);
+
+ err = request_irq(fh_sm_obj[id]->irq_no, fh_stepmotor_isr, IRQF_SHARED,
+ fh_sm_obj[id]->isrname, fh_sm_obj[id]);
+ if (err) {
+ dev_err(&pdev->dev, "request_irq:%d failed, %d\n",
+ fh_sm_obj[id]->irq_no, err);
+ err = -ENXIO;
+ goto fail_no_ioremap;
+ }
+ fh_stepmotor_init_hw_param(fh_sm_obj[id]);
+
+ fh_stepmotor_device[id] = kzalloc(sizeof(struct miscdevice),GFP_KERNEL);
+ fh_stepmotor_device[id]->minor = MISC_DYNAMIC_MINOR;
+ fh_stepmotor_device[id]->fops = &fh_stepmotor_fops;
+ memset(devstr[id],0,40);
+ sprintf(devstr[id], FH_SM_MISC_DEVICE_NAME, id);
+ fh_stepmotor_device[id]->name = devstr[id];
+ err = misc_register(fh_stepmotor_device[id]);
+
+ if (err < 0) {
+ pr_err("%s: ERROR: %s registration failed", __func__,
+ FH_SM_DEVICE_NAME);
+ err = -ENXIO;
+ goto misc_error;
+ }
+
+ return 0;
+
+misc_error:
+ free_irq(fh_sm_obj[id]->irq_no, &fh_sm_obj);
+
+fail_no_ioremap:
+ iounmap(fh_sm_obj[id]->regs);
+
+ return err;
+}
+
+static int __exit fh_stepmotor_remove(struct platform_device *pdev)
+{
+ misc_deregister(fh_stepmotor_device[pdev->id]);
+ kfree(fh_stepmotor_device[pdev->id]);
+ free_irq(fh_sm_obj[pdev->id]->irq_no, &fh_sm_obj);
+ iounmap(fh_sm_obj[pdev->id]->regs);
+ return 0;
+}
+
+
+
+
+
+
+static int __init fh_stepmotor_init(void)
+{
+ return platform_driver_register(&fh_stepmotor_driver);
+
+}
+
+static void __exit fh_stepmotor_exit(void)
+{
+
+ platform_driver_unregister(&fh_stepmotor_driver);
+}
+module_init(fh_stepmotor_init);
+module_exit(fh_stepmotor_exit);
+
+MODULE_AUTHOR("Fullhan");
+MODULE_DESCRIPTION("Misc Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform: FH StepMotor");
diff --git a/drivers/misc/fh_stepmotor.h b/drivers/misc/fh_stepmotor.h
new file mode 100644
index 00000000..70f6ab0c
--- /dev/null
+++ b/drivers/misc/fh_stepmotor.h
@@ -0,0 +1,34 @@
+
+#ifndef FH_STEPMOTOR_H_
+#define FH_STEPMOTOR_H_
+
+#include <linux/ioctl.h>
+
+#include "fh_stepmotor_hw.h"
+
+
+#define FH_SM_DEVICE_NAME "fh_stepmotor"
+#define FH_SM_PLAT_DEVICE_NAME "fh_stepmotor"
+
+#define FH_SM_MISC_DEVICE_NAME "fh_stepmotor%d"
+
+
+
+#define MAX_FHSM_NR (2)
+
+#define FH_SM_IOCTL_MAGIC 's'
+#define RESERVERD _IO(FH_SM_IOCTL_MAGIC, 0)
+#define FH_SM_SET_PARAM _IOWR(FH_SM_IOCTL_MAGIC, 1, __u32)
+#define FH_SM_START_SYNC _IOWR(FH_SM_IOCTL_MAGIC, 2, __u32)
+#define FH_SM_STOP _IOWR(FH_SM_IOCTL_MAGIC, 3, __u32)
+#define FH_SM_SET_LUT _IOWR(FH_SM_IOCTL_MAGIC, 4, __u32)
+#define FH_SM_GET_LUT _IOWR(FH_SM_IOCTL_MAGIC, 5, __u32)
+#define FH_SM_GET_PARAM _IOWR(FH_SM_IOCTL_MAGIC, 6, __u32)
+#define FH_SM_START_ASYNC _IOWR(FH_SM_IOCTL_MAGIC, 7, __u32)
+#define FH_SM_GET_CUR_CYCLE _IOWR(FH_SM_IOCTL_MAGIC, 8, __u32)
+
+
+
+
+
+#endif /* FH_STEPMOTOR_H_ */
diff --git a/drivers/misc/fh_stepmotor_hw.c b/drivers/misc/fh_stepmotor_hw.c
new file mode 100644
index 00000000..90fef5d9
--- /dev/null
+++ b/drivers/misc/fh_stepmotor_hw.c
@@ -0,0 +1,256 @@
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include <mach/pmu.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+
+#include "fh_stepmotor.h"
+
+
+irqreturn_t fh_stepmotor_isr(int irq, void *dev_id)
+{
+ struct fh_sm_obj_t* obj = (struct fh_sm_obj_t*)dev_id;
+
+ writel(0,obj->regs+MOTOR_INT_EN);
+ writel(0,obj->regs+MOTOR_INT_STATUS);
+ writel(1,obj->regs+MOTOR_INT_EN);
+
+ complete_all(&obj->run_complete);
+
+ return IRQ_HANDLED;
+}
+
+
+int fh_stepmotor_is_busy(struct fh_sm_obj_t* obj)
+{
+ int busy = readl(obj->regs+MOTOR_STATUS0)&0x01;
+ return busy;
+}
+
+
+void fh_stepmotor_set_hw_param(struct fh_sm_obj_t* obj,struct fh_sm_param* param)
+{
+ unsigned int reg;
+ // mode
+ reg = readl(obj->regs+MOTOR_MODE);
+ reg &= (~0x3);
+ reg |= param->mode&0x3;
+ // direction
+ if (param->direction) {
+ reg |= 0x1<<4;
+ } else {
+ reg &= (~(0x1<<4));
+ }
+ // inverse A/B
+ if (param->output_invert_A) {
+ reg |= 0x1<<5;
+ } else {
+ reg &= (~(0x1<<5));
+ }
+ if (param->output_invert_B) {
+ reg |= 0x1<<6;
+ } else {
+ reg &= (~(0x1<<6));
+ }
+ // microstep
+ reg &= (~(0xf<<8));
+ reg |= ((param->timingparam.microstep & 0xf)<<8);
+ writel(reg,obj->regs+MOTOR_MODE);
+
+ // clk
+ reg = readl(obj->regs+MOTOR_TIMING0);
+ reg = (param->timingparam.period<<16)|param->timingparam.counter;
+ writel(reg,obj->regs+MOTOR_TIMING0); // clk div 10*10
+
+
+ //copy
+ reg = readl(obj->regs+MOTOR_TIMING1);
+ reg &= (~0xff);
+ reg |= (param->timingparam.copy & 0xff);
+ writel(reg,obj->regs+MOTOR_TIMING1); // clk div 10*10
+
+
+
+ if (fh_sm_manual_4 == param->mode || fh_sm_manual_8 == param->mode) {
+ writel(param->manual_pwm_choosenA, obj->regs+MOTOR_MANUAL_CONFIG0);
+ writel(param->manual_pwm_choosenB, obj->regs+MOTOR_MANUAL_CONFIG1);
+ }
+
+
+
+
+
+
+
+}
+
+void fh_stepmotor_get_hw_param(struct fh_sm_obj_t* obj,struct fh_sm_param* param)
+{
+ unsigned int reg;
+ // mode
+ reg = readl(obj->regs+MOTOR_MODE);
+
+ param->mode = reg&0x3;
+ param->direction = (reg>>4)&0x1;
+ param->output_invert_A = (reg>>5)&0x1;
+ param->output_invert_B = (reg>>6)&0x1;
+
+
+ // microstep
+ param->timingparam.microstep = (reg>>8)&0xf;
+
+
+ // clk
+ reg = readl(obj->regs+MOTOR_TIMING0);
+ param->timingparam.period = (reg>>16);
+ param->timingparam.counter = reg&0xffff;
+
+
+ //copy
+ reg = readl(obj->regs+MOTOR_TIMING1);
+ param->timingparam.copy = reg & 0xff;
+
+ if (fh_sm_manual_4 == param->mode || fh_sm_manual_8 == param->mode) {
+ param->manual_pwm_choosenA = readl(obj->regs+MOTOR_MANUAL_CONFIG0);
+ param->manual_pwm_choosenB = readl(obj->regs+MOTOR_MANUAL_CONFIG1);
+ }
+}
+
+
+
+int fh_stepmotor_start_sync(struct fh_sm_obj_t* obj,int cycles)
+{
+ int fin = 0;
+ unsigned int regcycle = 0;
+ //cycle
+ if (cycles <= 0) return 0;
+
+ reinit_completion(&obj->run_complete);
+
+ cycles -=1;
+ regcycle = readl(obj->regs+MOTOR_TIMING1);
+ regcycle = regcycle & (0x0000ffff);
+ regcycle = regcycle|((cycles<<16)&0xffff0000);
+ writel(regcycle,obj->regs+MOTOR_TIMING1);
+
+ writel(1,obj->regs+MOTOR_CTRL);
+ wait_for_completion_interruptible(&obj->run_complete);
+ fin = (readl(obj->regs+MOTOR_STATUS0)>>8)&0x1ffff;
+
+ return fin;
+
+}
+
+void fh_stepmotor_start_async(struct fh_sm_obj_t* obj,int cycles)
+{
+ unsigned int regcycle = 0;
+
+ if (cycles <= 0) return;
+ cycles -= 1;
+ regcycle = readl(obj->regs+MOTOR_TIMING1);
+ regcycle = regcycle & (0x0000ffff);
+ regcycle = regcycle|((cycles<<16)&0xffff0000);
+ writel(regcycle,obj->regs+MOTOR_TIMING1);
+
+ writel(1,obj->regs+MOTOR_CTRL);
+
+}
+
+
+int fh_stepmotor_stop(struct fh_sm_obj_t* obj)
+{
+ int fin = 0;
+ if (fh_stepmotor_is_busy(obj)) {
+ reinit_completion(&obj->run_complete);
+ writel(0,obj->regs+MOTOR_CTRL);
+ wait_for_completion_interruptible(&obj->run_complete);
+ //wait_for_completion_interruptible_timeout(&obj->run_complete, HZ);
+
+ }
+ fin = (readl(obj->regs+MOTOR_STATUS0)>>8)&0x1ffff;
+ return fin;
+}
+int fh_stepmotor_get_current_cycle(struct fh_sm_obj_t* obj)
+{
+
+
+ int fin = (readl(obj->regs+MOTOR_STATUS0)>>8)&0x1ffff;
+
+ return fin;
+}
+
+
+int fh_stepmotor_set_lut(struct fh_sm_obj_t* obj,struct fh_sm_lut* lut)
+{
+
+ int i = 0;
+ for (i = 0; i< lut->lutsize/sizeof(u32);i++) {
+ writel(lut->lut[i],obj->regs+MOTOR_MEM+i*4);
+ }
+
+
+
+ return 5;
+}
+int fh_stepmotor_get_lutsize(struct fh_sm_obj_t* obj)
+{
+ return 256;
+}
+int fh_stepmotor_get_lut(struct fh_sm_obj_t* obj,struct fh_sm_lut* lut)
+{
+ int i;
+ for (i = 0; i< lut->lutsize/sizeof(u32);i++) {
+ lut->lut[i] = readl(obj->regs+MOTOR_MEM+i*4);
+ }
+ //lut->lut[0] = 0xfedc;
+
+ return 5;
+}
+const u32 fhsm_deflut[] = {
+0x00000080,0x0003007f,0x0006007f,0x0009007f,0x000c007f,0x000f007f,0x0012007e,0x0015007e,
+0x0018007d,0x001c007c,0x001f007c,0x0022007b,0x0025007a,0x00280079,0x002b0078,0x002e0077,
+0x00300076,0x00330075,0x00360073,0x00390072,0x003c0070,0x003f006f,0x0041006d,0x0044006c,
+0x0047006a,0x00490068,0x004c0066,0x004e0064,0x00510062,0x00530060,0x0055005e,0x0058005c,
+0x005a005a,0x005c0058,0x005e0055,0x00600053,0x00620051,0x0064004e,0x0066004c,0x00680049,
+0x006a0047,0x006c0044,0x006d0041,0x006f003f,0x0070003c,0x00720039,0x00730036,0x00750033,
+0x00760030,0x0077002e,0x0078002b,0x00790028,0x007a0025,0x007b0022,0x007c001f,0x007c001c,
+0x007d0018,0x007e0015,0x007e0012,0x007f000f,0x007f000c,0x007f0009,0x007f0006,0x007f0003,
+};
+
+
+void fh_stepmotor_init_hw_param(struct fh_sm_obj_t* obj)
+{
+ int i = 0;
+ // param
+ writel(0,obj->regs+MOTOR_MODE);
+ writel(0x800000,obj->regs+MOTOR_TIMING0); // clk div 128*1
+ writel(0x10010,obj->regs+MOTOR_TIMING1);
+ writel(0,obj->regs+MOTOR_MANUAL_CONFIG0);
+ writel(0,obj->regs+MOTOR_MANUAL_CONFIG1);
+ writel(1,obj->regs+MOTOR_INT_EN);
+ // def lut
+ for (i = 0; i< 64;i++) {
+ writel(fhsm_deflut[i],obj->regs+MOTOR_MEM+i*4);
+ }
+}
+
+
+
+
+
diff --git a/drivers/misc/fh_stepmotor_hw.h b/drivers/misc/fh_stepmotor_hw.h
new file mode 100644
index 00000000..a468282d
--- /dev/null
+++ b/drivers/misc/fh_stepmotor_hw.h
@@ -0,0 +1,86 @@
+
+#ifndef FH_STEPMOTOR_HW_H_
+#define FH_STEPMOTOR_HW_H_
+
+#include <linux/ioctl.h>
+
+
+
+
+
+#define MAX_FHSM_NR (2)
+
+
+
+#define MOTOR_CTRL (0x0)
+#define MOTOR_RESET (0x4)
+#define MOTOR_MODE (0x8)
+#define MOTOR_TIMING0 (0xc)
+#define MOTOR_TIMING1 (0x10)
+#define MOTOR_MANUAL_CONFIG0 (0x14)
+#define MOTOR_MANUAL_CONFIG1 (0x18)
+#define MOTOR_INT_EN (0x1c)
+#define MOTOR_INT_STATUS (0x20)
+#define MOTOR_STATUS0 (0x24)
+
+#define MOTOR_MEM (0x100)
+
+
+
+enum fh_sm_mode {
+ fh_sm_constant = 0,
+ fh_sm_high = 1,
+ fh_sm_manual_4 = 2,
+ fh_sm_manual_8 = 3,
+};
+struct fh_sm_timingparam {
+ int period;
+ int counter;
+ int copy;
+ int microstep;
+};
+
+
+struct fh_sm_param
+{
+ enum fh_sm_mode mode;
+ int direction;
+ int output_invert_A;
+ int output_invert_B;
+ unsigned int manual_pwm_choosenA;// please lookup doc to set
+ unsigned int manual_pwm_choosenB;// please lookup doc to set
+ struct fh_sm_timingparam timingparam;
+};
+
+struct fh_sm_lut
+{
+ int lutsize;
+ int *lut;
+};
+
+struct fh_sm_obj_t{
+ int irq_no;
+ void* regs;
+ struct clk *clk;
+ struct completion run_complete;
+ char isrname[24];
+};
+
+
+irqreturn_t fh_stepmotor_isr(int irq, void *dev_id);
+int fh_stepmotor_is_busy(struct fh_sm_obj_t *obj);
+void fh_stepmotor_set_hw_param(struct fh_sm_obj_t *obj,
+ struct fh_sm_param *param);
+void fh_stepmotor_get_hw_param(struct fh_sm_obj_t *obj,
+ struct fh_sm_param *param);
+int fh_stepmotor_start_sync(struct fh_sm_obj_t *obj,
+ int cycles);
+void fh_stepmotor_start_async(struct fh_sm_obj_t *obj,
+ int cycles);
+int fh_stepmotor_stop(struct fh_sm_obj_t *obj);
+int fh_stepmotor_get_current_cycle(struct fh_sm_obj_t *obj);
+int fh_stepmotor_set_lut(struct fh_sm_obj_t *obj,struct fh_sm_lut *lut);
+int fh_stepmotor_get_lutsize(struct fh_sm_obj_t *obj);
+int fh_stepmotor_get_lut(struct fh_sm_obj_t* obj,struct fh_sm_lut *lut);
+void fh_stepmotor_init_hw_param(struct fh_sm_obj_t *obj);
+#endif /* FH_STEPMOTOR_HW_H_ */
diff --git a/drivers/misc/fh_tsensor.c b/drivers/misc/fh_tsensor.c
new file mode 100644
index 00000000..0fcbc162
--- /dev/null
+++ b/drivers/misc/fh_tsensor.c
@@ -0,0 +1,185 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/fh_rtc_v2.h>
+
+#define DEVICE_NAME "fh_tsensor"
+
+#define TSENSOR_IOCTL_MAGIC 't'
+#define TSENSOR_GET_TEMP _IOWR(TSENSOR_IOCTL_MAGIC, 1, int)
+#define TSENSOR_GET_DATA _IOWR(TSENSOR_IOCTL_MAGIC, 2, int)
+
+static const struct file_operations fh_tsensor_fops;
+
+static struct miscdevice fh_tsensor_miscdev = {
+ .fops = &fh_tsensor_fops,
+ .name = DEVICE_NAME,
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
+static void create_proc(void);
+static void remove_proc(void);
+
+long fh_tsensor_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int data, temp;
+
+ if (unlikely(_IOC_TYPE(cmd) != TSENSOR_IOCTL_MAGIC))
+ return -ENOTTY;
+
+ switch (cmd)
+ {
+ case TSENSOR_GET_TEMP:
+ if (fh_rtc_get_tsensor_data(&data, &temp))
+ return -EIO;
+ if (copy_to_user((void __user *)arg, &temp, sizeof(temp)))
+ return -EIO;
+ break;
+ case TSENSOR_GET_DATA:
+ if (fh_rtc_get_tsensor_data(&data, &temp))
+ return -EIO;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data)))
+ return -EIO;
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int fh_tsensor_probe(struct platform_device *pdev)
+{
+ create_proc();
+ return misc_register(&fh_tsensor_miscdev);
+}
+
+static int fh_tsensor_remove(struct platform_device *pdev)
+{
+ remove_proc();
+ misc_deregister(&fh_tsensor_miscdev);
+ return 0;
+}
+
+int fh_rtc_get_tsensor_data(int *data, int *temp);
+
+static int fh_tsensor_open(struct inode *ip, struct file *fp)
+{
+ return 0;
+}
+
+static int fh_tsensor_close(struct inode *ip, struct file *fp)
+{
+ return 0;
+}
+
+static const struct file_operations fh_tsensor_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .unlocked_ioctl = fh_tsensor_ioctl,
+ .release = fh_tsensor_close,
+ .open = fh_tsensor_open,
+};
+
+static const struct of_device_id fh_tsensor_of_match[] = {
+ {.compatible = "fh,fh-tsensor",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_tsensor_of_match);
+
+static struct platform_driver fh_tsensor_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .of_match_table = fh_tsensor_of_match,
+ },
+ .probe = fh_tsensor_probe,
+ .remove = fh_tsensor_remove,
+};
+
+module_platform_driver(fh_tsensor_driver);
+
+MODULE_AUTHOR("Fullhan");
+MODULE_DESCRIPTION("Fullhan tsensor device driver");
+MODULE_LICENSE("GPL");
+
+/****************************debug proc*****************************/
+
+#define PROC_NAME "driver/"DEVICE_NAME
+static struct proc_dir_entry *proc_file;
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int data, temp, ret;
+
+ ret = fh_rtc_get_tsensor_data(&data, &temp);
+ if (ret) {
+ seq_printf(sfile, "get_tsensor_data error %d\n", ret);
+ return 0;
+ }
+
+ seq_printf(sfile, "raw data: %d\n", data);
+ seq_printf(sfile, "temp : %d.%01d\n", temp / 10, abs(temp % 10));
+
+ return 0;
+}
+
+static const struct seq_operations fh_dwi2s_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &fh_dwi2s_seq_ops);
+}
+
+static struct file_operations fh_tsensor_proc_ops =
+{
+ .owner = THIS_MODULE,
+ .open = proc_open,
+ .read = seq_read,
+};
+
+static void create_proc(void)
+{
+ proc_file = proc_create(PROC_NAME, 0644, NULL, &fh_tsensor_proc_ops);
+
+ if (proc_file == NULL)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, DEVICE_NAME);
+}
+
+static void remove_proc(void)
+{
+ remove_proc_entry(PROC_NAME, NULL);
+}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index cff58297..35563022 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2805,6 +2805,17 @@ void mmc_rescan(struct work_struct *work)
goto out;
}
+ /* rescan 2 times when detect mmc */
+ if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_max_num) {
+ if (host->rescan_count >= host->rescan_max_num) {
+ mmc_power_off(host);
+ mmc_release_host(host);
+ goto out;
+ } else {
+ host->rescan_count++;
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
break;
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index f09148a4..770938a6 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -690,14 +690,14 @@ static ssize_t mmc_dsr_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct mmc_card *card = mmc_dev_to_card(dev);
- struct mmc_host *host = card->host;
-
- if (card->csd.dsr_imp && host->dsr_req)
- return sprintf(buf, "0x%x\n", host->dsr);
- else
- /* return default DSR value */
- return sprintf(buf, "0x%x\n", 0x404);
+ struct mmc_card *card = mmc_dev_to_card(dev);
+ struct mmc_host *host = card->host;
+
+ if (card->csd.dsr_imp && host->dsr_req)
+ return sprintf(buf, "0x%x\n", host->dsr);
+ else
+ /* return default DSR value */
+ return sprintf(buf, "0x%x\n", 0x404);
}
static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL);
@@ -765,8 +765,9 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
* to switch to 1.8V signaling level. If the card has failed
* repeatedly to switch however, skip this.
*/
- if (retries && mmc_host_uhs(host))
+ if (retries && mmc_host_uhs(host)) {
ocr |= SD_OCR_S18R;
+ }
/*
* If the host can supply more than 150mA at current voltage,
@@ -780,6 +781,7 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
if (err)
return err;
+
/*
* In case CCS and S18A in the response is set, start Signal Voltage
* Switch procedure. SPI mode doesn't support CMD11.
@@ -855,7 +857,6 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
err = mmc_app_send_scr(card, card->raw_scr);
if (err)
return err;
-
err = mmc_decode_scr(card);
if (err)
return err;
@@ -866,7 +867,6 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
err = mmc_read_ssr(card);
if (err)
return err;
-
/* Erase init depends on CSD and SSR */
mmc_init_erase(card);
@@ -895,7 +895,6 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
*/
if (!reinit) {
int ro = mmc_sd_get_ro(host);
-
if (ro < 0) {
pr_warn("%s: host does not support reading read-only switch, assuming write-enable\n",
mmc_hostname(host));
@@ -966,6 +965,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (host->ops->init_card)
host->ops->init_card(host, card);
+
/*
* For native busses: get card RCA and quit open drain mode.
*/
@@ -974,7 +974,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (err)
goto free_card;
}
-
if (!oldcard) {
err = mmc_sd_get_csd(host, card);
if (err)
@@ -998,11 +997,9 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
if (err)
goto free_card;
}
-
err = mmc_sd_setup_card(host, card, oldcard != NULL);
if (err)
goto free_card;
-
/* Initialization sequence for UHS-I cards */
if (rocr & SD_ROCR_S18A) {
err = mmc_sd_init_uhs_card(card);
@@ -1265,8 +1262,9 @@ int mmc_attach_sd(struct mmc_host *host)
* Detect and init the card.
*/
err = mmc_sd_init_card(host, rocr, NULL);
- if (err)
+ if (err) {
goto err;
+ }
mmc_release_host(host);
err = mmc_add_card(host->card);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5274f503..61d4f4da 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -484,6 +484,21 @@ config MMC_SPI
controllers.
If unsure, or if your system has no SPI master driver, say N.
+config MMC_FH
+ tristate "FH Memory Card Interface"
+ depends on ARM
+ help
+ This selects support for the Synopsys DesignWare Mobile Storage IP
+ block, this provides host support for SD and MMC interfaces, in both
+ PIO and external DMA modes.
+
+config MMC_FH_IDMAC
+ bool "Internal DMAC interface"
+ depends on MMC_FH
+ help
+ This selects support for the internal DMAC block within the Synopsys
+ Designware Mobile Storage IP block. This disables the external DMA
+ interface.
config MMC_S3C
tristate "Samsung S3C SD/MMC Card Interface support"
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index e2bdaaf4..bdfa6b07 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_MMC_SDHCI_ST) += sdhci-st.o
obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32) += sdhci-pic32.o
obj-$(CONFIG_MMC_SDHCI_BRCMSTB) += sdhci-brcmstb.o
+obj-$(CONFIG_MMC_FH) += fhmci/
ifeq ($(CONFIG_CB710_DEBUG),y)
CFLAGS-cb710-mmc += -DDEBUG
endif
diff --git a/drivers/mmc/host/fhmci/Makefile b/drivers/mmc/host/fhmci/Makefile
new file mode 100644
index 00000000..89241d7c
--- /dev/null
+++ b/drivers/mmc/host/fhmci/Makefile
@@ -0,0 +1,3 @@
+
+obj-$(CONFIG_MMC_FH) += fh_mci.o
+fh_mci-y := fhmci.o
diff --git a/drivers/mmc/host/fhmci/fhmci.c b/drivers/mmc/host/fhmci/fhmci.c
new file mode 100644
index 00000000..06523946
--- /dev/null
+++ b/drivers/mmc/host/fhmci/fhmci.c
@@ -0,0 +1,2122 @@
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/card.h>
+#include <linux/slab.h>
+
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+#include <linux/workqueue.h>
+#include <linux/freezer.h>
+#include <asm/dma.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <linux/uaccess.h>
+#include <linux/mmc/card.h>
+#include <linux/clk.h>
+#include "fhmci_reg.h"
+#include <mach/fh_mci_plat.h>
+
+#include <mach/pmu.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+
+extern int trace_level;
+#define FHMCI_TRACE_LEVEL 5
+
+#define FHMCI_TRACE_FMT KERN_INFO
+#define ID_SD0 0
+#define ID_SD1 1
+#define ID_SD2 2
+
+
+#define HS400_TUNING_START_PHASE 1
+#define HS400_TUNING_END_PHASE 15
+#define NOT_FOUND -1
+
+
+#define POWER_ON 1
+#define POWER_OFF 0
+#define FORCE_ENABLE 1
+#define FORCE_DISABLE 0
+
+
+#define CARD_UNPLUGED 1
+#define CARD_PLUGED 0
+
+#define ENABLE 1
+#define DISABLE 0
+
+#define FH_MCI_DETECT_TIMEOUT (HZ/4)
+
+#define FH_MCI_REQUEST_TIMEOUT (5 * HZ)
+
+#define MAX_RETRY_COUNT 100
+#define MAX_MCI_HOST (2) /* max num of host on soc */
+
+/*sdio 3.0*/
+#define DRV_PHASE_DFLT (0x6<<23)
+#define SMPL_PHASE_DFLT (0x1<<16)
+
+
+
+#define fhmci_trace(level, msg...) do { \
+ if ((level) >= trace_level) { \
+ printk(FHMCI_TRACE_FMT "%s:%d: ", __func__, __LINE__); \
+ printk(msg); \
+ printk("\n"); \
+ } \
+} while (0)
+
+#define fhmci_assert(cond) do { \
+ if (!(cond)) {\
+ printk(KERN_ERR "Assert:fhmci:%s:%d\n", \
+ __func__, \
+ __LINE__); \
+ BUG(); \
+ } \
+} while (0)
+
+#define fhmci_error(s...) do { \
+ printk(KERN_ERR "fhmci:%s:%d: ", __func__, __LINE__); \
+ printk(s); \
+ printk("\n"); \
+} while (0)
+
+#define fhmci_readl(addr) ({unsigned int reg = readl(addr); \
+ fhmci_trace(1, "readl(0x%04x) = 0x%08X", (unsigned int) addr, reg); \
+ reg; })
+
+#define fhmci_writel(v, addr) do { \
+ writel(v, addr); \
+ fhmci_trace(1, "writel(0x%04x) = 0x%08X",\
+ (unsigned int)addr, (unsigned int)(v)); \
+} while (0)
+
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+#ifndef TRUE
+#define TRUE (!(FALSE))
+#endif
+
+#define SD_POWER_ON 1
+#define SD_POWER_OFF 0
+#define DRIVER_NAME "fh_mci"
+
+static unsigned int retry_count = MAX_RETRY_COUNT;
+static unsigned int request_timeout = FH_MCI_REQUEST_TIMEOUT;
+int trace_level = FHMCI_TRACE_LEVEL;
+
+/*#define FH_SDIO30*/
+
+
+#ifdef MODULE
+MODULE_PARM_DESC(detect_timer, "card detect time (default:500ms)");
+
+module_param(retry_count, uint, 0600);
+MODULE_PARM_DESC(retry_count, "retry count times (default:100)");
+
+module_param(request_timeout, uint, 0600);
+MODULE_PARM_DESC(request_timeout, "Request timeout time (default:3s)");
+
+module_param(trace_level, int, 0600);
+MODULE_PARM_DESC(trace_level, "FHMCI_TRACE_LEVEL");
+
+#endif
+
+#ifdef FH_SDIO30
+static const u8 tuning_blk_4bit[] = {
+ 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
+ 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
+ 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
+ 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
+ 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
+ 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
+ 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
+ 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
+};
+
+static const u8 tuning_blk_8bit[] = {
+ 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
+ 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
+ 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
+ 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
+ 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
+ 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
+ 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
+ 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
+ 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
+ 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
+ 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
+ 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
+ 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
+};
+struct tuning_blk_info {
+ u8 *blk;
+ unsigned int blk_size;
+};
+#define TUNING_START_PHASE 0
+#define TUNING_END_PHASE 15
+#define HIMCI_PHASE_SCALE 16
+#endif
+
+
+/* reset MMC host controler */
+static void fh_mci_sys_reset(struct fhmci_host *host)
+{
+ unsigned int reg_value;
+ unsigned long flags;
+
+ fhmci_trace(2, "reset");
+
+ local_irq_save(flags);
+
+ reg_value = fhmci_readl(host->base + MCI_BMOD);
+ reg_value |= BMOD_SWR;
+ fhmci_writel(reg_value, host->base + MCI_BMOD);
+ udelay(50);
+
+ reg_value = fhmci_readl(host->base + MCI_BMOD);
+ reg_value |= BURST_INCR;
+ fhmci_writel(reg_value, host->base + MCI_BMOD);
+
+ reg_value = fhmci_readl(host->base + MCI_CTRL);
+ reg_value |= CTRL_RESET | FIFO_RESET | DMA_RESET;
+ fhmci_writel(reg_value, host->base + MCI_CTRL);
+
+ local_irq_restore(flags);
+}
+
+static void fh_mci_sys_undo_reset(struct fhmci_host *host)
+{
+ unsigned long flags;
+
+ fhmci_trace(2, "undo reset");
+
+ local_irq_save(flags);
+ local_irq_restore(flags);
+}
+
+static void fh_mci_ctrl_power(struct fhmci_host *host, unsigned int flag)
+{
+ fhmci_trace(2, "begin");
+
+}
+
+/**********************************************
+ *1: card off
+ *0: card on
+ ***********************************************/
+static unsigned int fh_mci_sys_card_detect(struct fhmci_host *host)
+{
+ unsigned int card_status = readl(host->base + MCI_CDETECT);
+
+ return card_status & FHMCI_CARD0;
+}
+
+/**********************************************
+ *1: card readonly
+ *0: card read/write
+ ***********************************************/
+static unsigned int fh_mci_ctrl_card_readonly(struct fhmci_host *host)
+{
+ unsigned int card_value = fhmci_readl(host->base + MCI_WRTPRT);
+
+ return card_value & FHMCI_CARD0;
+}
+
+static int fh_mci_wait_cmd(struct fhmci_host *host)
+{
+ int wait_retry_count = 0;
+ unsigned int reg_data = 0;
+ unsigned long flags;
+
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+
+ while (1) {
+ /*
+ * Check if CMD::start_cmd bit is clear.
+ * start_cmd = 0 means MMC Host controller has loaded registers
+ * and next command can be loaded in.
+ */
+ reg_data = fhmci_readl(host->base + MCI_CMD);
+ if ((reg_data & START_CMD) == 0)
+ return 0;
+
+ /* Check if Raw_Intr_Status::HLE bit is set. */
+ spin_lock_irqsave(&host->lock, flags);
+ reg_data = fhmci_readl(host->base + MCI_RINTSTS);
+ if (reg_data & HLE_INT_STATUS) {
+ reg_data &= (~SDIO_INT_STATUS);
+ fhmci_writel(reg_data, host->base + MCI_RINTSTS);
+ spin_unlock_irqrestore(&host->lock, flags);
+ fhmci_trace(3, "Other CMD is running,"
+ "please operate cmd again!");
+ return 1;
+ }
+
+ spin_unlock_irqrestore(&host->lock, flags);
+ udelay(100);
+
+ /* Check if number of retries for this are over. */
+ wait_retry_count++;
+ if (wait_retry_count >= retry_count) {
+ fhmci_trace(3, "send cmd is timeout!");
+ return -1;
+ }
+ }
+}
+
+static void fh_mci_control_cclk(struct fhmci_host *host, unsigned int flag)
+{
+ unsigned int reg;
+ union cmd_arg_s cmd_reg;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+
+ reg = fhmci_readl(host->base + MCI_CLKENA);
+ if (flag == ENABLE)
+ reg |= CCLK_ENABLE;
+ else
+ reg &= 0xffff0000;
+ fhmci_writel(reg, host->base + MCI_CLKENA);
+
+ cmd_reg.cmd_arg = fhmci_readl(host->base + MCI_CMD);
+ cmd_reg.bits.start_cmd = 1;
+ cmd_reg.bits.update_clk_reg_only = 1;
+ fhmci_writel(cmd_reg.cmd_arg, host->base + MCI_CMD);
+ if (fh_mci_wait_cmd(host) != 0)
+ fhmci_trace(3, "disable or enable clk is timeout!");
+}
+
+static void fh_mci_set_cclk(struct fhmci_host *host, unsigned int cclk)
+{
+ unsigned int reg_value;
+ union cmd_arg_s clk_cmd;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(cclk);
+
+
+ /*
+ * set card clk divider value,
+ * clk_divider = Fmmcclk/(Fmmc_cclk * 2)
+ */
+
+ if (host->id == 0) {
+ if (host->bus_hz <= cclk)
+ reg_value = 0;
+ else {
+ reg_value = host->bus_hz / (cclk * 2);
+ if (host->bus_hz % (cclk * 2))
+ reg_value++;
+ }
+ } else if (host->id == 1) {
+ if (host->bus_hz <= cclk)
+ reg_value = 0;
+ else {
+ reg_value = host->bus_hz / (cclk * 2);
+ if (host->bus_hz % (cclk * 2))
+ reg_value++;
+ }
+ } else if (host->id == 2) {
+ if (host->bus_hz <= cclk)
+ reg_value = 0;
+ else {
+ reg_value = host->bus_hz / (cclk * 2);
+ if (host->bus_hz % (cclk * 2))
+ reg_value++;
+ }
+ } else {
+ fhmci_error("fhmci host id error!");
+ return;
+ }
+
+ fhmci_writel(reg_value, host->base + MCI_CLKDIV);
+
+
+ clk_cmd.cmd_arg = fhmci_readl(host->base + MCI_CMD);
+ clk_cmd.bits.start_cmd = 1;
+ clk_cmd.bits.update_clk_reg_only = 1;
+ fhmci_writel(clk_cmd.cmd_arg, host->base + MCI_CMD);
+
+ if (fh_mci_wait_cmd(host) != 0)
+ fhmci_trace(3, "set card clk divider is failed!");
+}
+
+static void fh_mci_init_card(struct fhmci_host *host)
+{
+ unsigned int tmp_reg = 0, tmp;
+ unsigned long flags;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ tmp = fhmci_readl(host->base + MCI_PWREN);
+ fh_mci_sys_reset(host);
+ fh_mci_ctrl_power(host, POWER_OFF);
+ udelay(500);
+ /* card power on */
+ fh_mci_ctrl_power(host, POWER_ON);
+ udelay(200);
+
+ fh_mci_sys_undo_reset(host);
+
+ /* set phase shift sdio3.0*/
+ /*tmp_reg |= SMPL_PHASE_DFLT | DRV_PHASE_DFLT;*/
+ /*fhmci_writel(tmp_reg, host->base + MCI_UHS_EXT);*/
+
+ /* set card read threshold */
+ /*fhmci_writel(RW_THRESHOLD_SIZE,
+ *host->base + MCI_READ_THRESHOLD_SIZE);
+ */
+
+ /* clear MMC host intr */
+ fhmci_writel(ALL_INT_CLR, host->base + MCI_RINTSTS);
+
+ spin_lock_irqsave(&host->lock, flags);
+ host->pending_events = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ /* MASK MMC host intr */
+ tmp_reg = fhmci_readl(host->base + MCI_INTMASK);
+ tmp_reg &= ~ALL_INT_MASK;
+ tmp_reg |= DATA_INT_MASK;
+ fhmci_writel(tmp_reg, host->base + MCI_INTMASK);
+
+ /* enable inner DMA mode and close intr of MMC host controler */
+ tmp_reg = fhmci_readl(host->base + MCI_CTRL);
+ tmp_reg &= ~INTR_EN;
+ tmp_reg |= USE_INTERNAL_DMA | INTR_EN;
+ fhmci_writel(tmp_reg, host->base + MCI_CTRL);
+
+
+ /* set timeout param */
+ fhmci_writel(DATA_TIMEOUT | RESPONSE_TIMEOUT, host->base + MCI_TIMEOUT);
+
+ /* set FIFO param */
+ if (host->fifo_depth > 15)
+ tmp = 0x5;
+ else
+ tmp = 0x2;
+
+ tmp_reg = ((tmp << 28) | ((host->fifo_depth / 2) << 16)
+ | (((host->fifo_depth / 2) + 1) << 0));
+ fhmci_writel(tmp_reg, host->base + MCI_FIFOTH);
+}
+
+static void fh_mci_idma_start(struct fhmci_host *host)
+{
+ unsigned int tmp;
+
+ fhmci_trace(2, "begin");
+ fhmci_writel(host->dma_paddr, host->base + MCI_DBADDR);
+ tmp = fhmci_readl(host->base + MCI_BMOD);
+ tmp |= BMOD_DMA_EN;
+ tmp |= BURST_INCR;
+ fhmci_writel(tmp, host->base + MCI_BMOD);
+}
+
+static void fh_mci_idma_stop(struct fhmci_host *host)
+{
+ unsigned int tmp_reg;
+
+ fhmci_trace(2, "begin");
+ tmp_reg = fhmci_readl(host->base + MCI_BMOD);
+ tmp_reg &= ~BMOD_DMA_EN;
+ tmp_reg |= BMOD_SWR;
+ fhmci_writel(tmp_reg, host->base + MCI_BMOD);
+}
+
+static int fh_mci_setup_data(struct fhmci_host *host, struct mmc_data *data)
+{
+ unsigned int sg_phyaddr, sg_length;
+ unsigned int i, ret = 0;
+ unsigned int data_size;
+ unsigned int max_des, des_cnt;
+ struct fhmci_des *des;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(data);
+
+ host->data = data;
+
+ if (data->flags & MMC_DATA_READ)
+ host->dma_dir = DMA_FROM_DEVICE;
+ else
+ host->dma_dir = DMA_TO_DEVICE;
+
+ host->dma_sg = data->sg;
+ host->dma_sg_num = dma_map_sg(mmc_dev(host->mmc),
+ data->sg, data->sg_len, host->dma_dir);
+ fhmci_assert(host->dma_sg_num);
+ fhmci_trace(2, "host->dma_sg_num is %d\n", host->dma_sg_num);
+ data_size = data->blksz * data->blocks;
+
+ if (data_size > (DMA_BUFFER * MAX_DMA_DES)) {
+ fhmci_error("mci request data_size is too big!\n");
+ ret = -1;
+ goto out;
+ }
+
+ fhmci_trace(2, "host->dma_paddr is 0x%08X,host->dma_vaddr is 0x%08X\n",
+ (unsigned int)host->dma_paddr,
+ (unsigned int)host->dma_vaddr);
+
+ max_des = (PAGE_SIZE/sizeof(struct fhmci_des));
+ des = (struct fhmci_des *)host->dma_vaddr;
+ des_cnt = 0;
+
+ for (i = 0; i < host->dma_sg_num; i++) {
+ sg_length = sg_dma_len(&data->sg[i]);
+ sg_phyaddr = sg_dma_address(&data->sg[i]);
+ fhmci_trace(2, "sg[%d] sg_length is 0x%08X, "
+ "sg_phyaddr is 0x%08X\n",
+ i, (unsigned int)sg_length,
+ (unsigned int)sg_phyaddr);
+ while (sg_length) {
+ des[des_cnt].idmac_des_ctrl = DMA_DES_OWN
+ | DMA_DES_NEXT_DES;
+ des[des_cnt].idmac_des_buf_addr = sg_phyaddr;
+ /* idmac_des_next_addr is paddr for dma */
+ des[des_cnt].idmac_des_next_addr = host->dma_paddr
+ + (des_cnt + 1) * sizeof(struct fhmci_des);
+
+ if (sg_length >= 0x1F00) {
+ des[des_cnt].idmac_des_buf_size = 0x1F00;
+ sg_length -= 0x1F00;
+ sg_phyaddr += 0x1F00;
+ } else {
+ /* FIXME:data alignment */
+ des[des_cnt].idmac_des_buf_size = sg_length;
+ sg_length = 0;
+ }
+
+ fhmci_trace(2, "des[%d] vaddr is 0x%08X", des_cnt,
+ (unsigned int)&des[des_cnt]);
+ fhmci_trace(2, "des[%d].idmac_des_ctrl is 0x%08X",
+ des_cnt, (unsigned int)des[des_cnt].idmac_des_ctrl);
+ fhmci_trace(2, "des[%d].idmac_des_buf_size is 0x%08X",
+ des_cnt, (unsigned int)des[des_cnt].idmac_des_buf_size);
+ fhmci_trace(2, "des[%d].idmac_des_buf_addr 0x%08X",
+ des_cnt, (unsigned int)des[des_cnt].idmac_des_buf_addr);
+ fhmci_trace(2, "des[%d].idmac_des_next_addr is 0x%08X",
+ des_cnt, (unsigned int)des[des_cnt].idmac_des_next_addr);
+ des_cnt++;
+ }
+
+ fhmci_assert(des_cnt < max_des);
+ }
+ des[0].idmac_des_ctrl |= DMA_DES_FIRST_DES;
+ des[des_cnt - 1].idmac_des_ctrl |= DMA_DES_LAST_DES;
+ des[des_cnt - 1].idmac_des_next_addr = 0;
+out:
+ return ret;
+}
+
+static int fh_mci_exec_cmd(struct fhmci_host *host,
+ struct mmc_command *cmd, struct mmc_data *data)
+{
+ volatile union cmd_arg_s cmd_regs;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(cmd);
+
+ host->cmd = cmd;
+
+ fhmci_writel(cmd->arg, host->base + MCI_CMDARG);
+ fhmci_trace(2, "arg_reg 0x%x, val 0x%x\n", MCI_CMDARG, cmd->arg);
+ cmd_regs.cmd_arg = fhmci_readl(host->base + MCI_CMD);
+ if (data) {
+ cmd_regs.bits.data_transfer_expected = 1;
+ if (data->flags & (MMC_DATA_WRITE | MMC_DATA_READ))
+ cmd_regs.bits.transfer_mode = 0;
+
+ if (data->flags & MMC_DATA_STREAM)
+ cmd_regs.bits.transfer_mode = 1;
+
+ if (data->flags & MMC_DATA_WRITE)
+ cmd_regs.bits.read_write = 1;
+ else if (data->flags & MMC_DATA_READ)
+ cmd_regs.bits.read_write = 0;
+ } else {
+ cmd_regs.bits.data_transfer_expected = 0;
+ cmd_regs.bits.transfer_mode = 0;
+ cmd_regs.bits.read_write = 0;
+ }
+ cmd_regs.bits.send_auto_stop = 0;
+#ifdef CONFIG_SEND_AUTO_STOP
+ if ((host->mrq->stop) && (!(host->is_tuning)))
+ cmd_regs.bits.send_auto_stop = 1;
+#endif
+
+ if (cmd == host->mrq->stop) {
+ cmd_regs.bits.stop_abort_cmd = 1;
+ cmd_regs.bits.wait_prvdata_complete = 0;
+ } else {
+ cmd_regs.bits.stop_abort_cmd = 0;
+ cmd_regs.bits.wait_prvdata_complete = 1;
+ }
+
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_NONE:
+ cmd_regs.bits.response_expect = 0;
+ cmd_regs.bits.response_length = 0;
+ cmd_regs.bits.check_response_crc = 0;
+ break;
+ case MMC_RSP_R1:
+ case MMC_RSP_R1B:
+ cmd_regs.bits.response_expect = 1;
+ cmd_regs.bits.response_length = 0;
+ cmd_regs.bits.check_response_crc = 1;
+ break;
+ case MMC_RSP_R2:
+ cmd_regs.bits.response_expect = 1;
+ cmd_regs.bits.response_length = 1;
+ cmd_regs.bits.check_response_crc = 1;
+ break;
+ case MMC_RSP_R3:
+ cmd_regs.bits.response_expect = 1;
+ cmd_regs.bits.response_length = 0;
+ cmd_regs.bits.check_response_crc = 0;
+ break;
+ default:
+ fhmci_error("fh_mci: unhandled response type %02x\n",
+ mmc_resp_type(cmd));
+ return -EINVAL;
+ }
+
+ fhmci_trace(2, "send cmd of card is cmd->opcode = %d ", cmd->opcode);
+ if (cmd->opcode == MMC_GO_IDLE_STATE)
+ cmd_regs.bits.send_initialization = 1;
+ else
+ cmd_regs.bits.send_initialization = 0;
+ /* CMD 11 check switch voltage */
+ if (cmd->opcode == SD_SWITCH_VOLTAGE)
+ cmd_regs.bits.volt_switch = 1;
+ else
+ cmd_regs.bits.volt_switch = 0;
+
+
+ cmd_regs.bits.card_number = 0;
+ cmd_regs.bits.cmd_index = cmd->opcode;
+ cmd_regs.bits.start_cmd = 1;
+ cmd_regs.bits.update_clk_reg_only = 0;
+ fhmci_writel(DATA_INT_MASK, host->base + MCI_RINTSTS);
+ fhmci_writel(cmd_regs.cmd_arg, host->base + MCI_CMD);
+ fhmci_trace(2, "cmd_reg 0x%x, val 0x%x\n", MCI_CMD, cmd_regs.cmd_arg);
+
+ if (fh_mci_wait_cmd(host) != 0) {
+ fhmci_trace(3, "send card cmd is failed!");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void fh_mci_finish_request(struct fhmci_host *host,
+ struct mmc_request *mrq)
+{
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(mrq);
+
+ host->mrq = NULL;
+ host->cmd = NULL;
+ host->data = NULL;
+
+ mmc_request_done(host->mmc, mrq);
+}
+
+static void fh_mci_cmd_done(struct fhmci_host *host, unsigned int stat)
+{
+ unsigned int i;
+ struct mmc_command *cmd = host->cmd;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(cmd);
+
+
+ for (i = 0; i < 4; i++) {
+ if (mmc_resp_type(cmd) == MMC_RSP_R2) {
+ cmd->resp[i] = fhmci_readl(host->base +
+ MCI_RESP3 - i * 0x4);
+ /* R2 must delay some time here ,
+ *when use UHI card, need check why
+ */
+ udelay(1000);
+ } else
+ cmd->resp[i] = fhmci_readl(host->base +
+ MCI_RESP0 + i * 0x4);
+ }
+
+ if (stat & RTO_INT_STATUS) {
+ cmd->error = -ETIMEDOUT;
+ fhmci_trace(3, "irq cmd status stat = 0x%x is timeout error!",
+ stat);
+ } else if (stat & (RCRC_INT_STATUS | RE_INT_STATUS)) {
+ cmd->error = -EILSEQ;
+ fhmci_trace(3, "irq cmd status stat = 0x%x is response error!",
+ stat);
+ }
+ host->cmd = NULL;
+}
+
+
+static void fh_mci_data_done(struct fhmci_host *host, unsigned int stat)
+{
+ struct mmc_data *data = host->data;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(data);
+
+
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir);
+
+ if (stat & (HTO_INT_STATUS | DRTO_INT_STATUS)) {
+ data->error = -ETIMEDOUT;
+ fhmci_trace(3, "irq data status stat = 0x%x is timeout error!",
+ stat);
+ } else if (stat & (EBE_INT_STATUS | SBE_INT_STATUS | FRUN_INT_STATUS
+ | DCRC_INT_STATUS)) {
+#ifndef CONFIG_MACH_FH8830_FPGA
+ data->error = -EILSEQ;
+#endif
+ fhmci_trace(3, "irq data status stat = 0x%x is data error!",
+ stat);
+ }
+
+ if (!data->error)
+ data->bytes_xfered = data->blocks * data->blksz;
+ else
+ data->bytes_xfered = 0;
+
+ host->data = NULL;
+}
+
+
+static int fh_mci_wait_cmd_complete(struct fhmci_host *host)
+{
+ unsigned int cmd_retry_count = 0;
+ unsigned long cmd_jiffies_timeout;
+ unsigned int cmd_irq_reg = 0;
+ struct mmc_command *cmd = host->cmd;
+ unsigned long flags;
+ unsigned int cmd_done = 0;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(cmd);
+
+ cmd_jiffies_timeout = jiffies + request_timeout;
+ while (1) {
+
+ do {
+ spin_lock_irqsave(&host->lock, flags);
+ cmd_irq_reg = readl(host->base + MCI_RINTSTS);
+
+ if (cmd_irq_reg & CD_INT_STATUS) {
+ fhmci_writel((CD_INT_STATUS | RTO_INT_STATUS
+ | RCRC_INT_STATUS | RE_INT_STATUS),
+ host->base + MCI_RINTSTS);
+ spin_unlock_irqrestore(&host->lock, flags);
+ cmd_done = 1;
+ break;
+ /*fh_mci_cmd_done(host, cmd_irq_reg);*/
+ /*return 0;*/
+ } else if (cmd_irq_reg & VOLT_SWITCH_INT_STATUS) {
+ fhmci_writel(VOLT_SWITCH_INT_STATUS,
+ host->base + MCI_RINTSTS);
+ spin_unlock_irqrestore(&host->lock, flags);
+ cmd_done = 1;
+ break;
+ /*fh_mci_cmd_done(host, cmd_irq_reg);*/
+ /*return 0;*/
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+ cmd_retry_count++;
+ } while (cmd_retry_count < retry_count &&
+ host->get_cd(host) != CARD_UNPLUGED);
+
+ cmd_retry_count = 0;
+
+ if ((host->card_status == CARD_UNPLUGED)
+ || (host->get_cd(host) == CARD_UNPLUGED)) {
+ cmd->error = -ETIMEDOUT;
+ return -1;
+ }
+ if (cmd_done) {
+ fh_mci_cmd_done(host, cmd_irq_reg);
+ return 0;
+ }
+
+ if (!time_before(jiffies, cmd_jiffies_timeout)) {
+ unsigned int i = 0;
+
+ for (i = 0; i < 4; i++) {
+ cmd->resp[i] = fhmci_readl(host->base
+ + MCI_RESP0 + i * 0x4);
+ printk(KERN_ERR "voltage switch read MCI_RESP");
+ printk(KERN_ERR "%d : 0x%x\n", i, cmd->resp[i]);
+ }
+ cmd->error = -ETIMEDOUT;
+ fhmci_trace(3, "wait cmd request complete is timeout!");
+ return -1;
+ }
+
+ schedule();
+ }
+}
+/*
+ * designware support send stop command automatically when
+ * read or wirte multi blocks
+ */
+#ifdef CONFIG_SEND_AUTO_STOP
+static int fh_mci_wait_auto_stop_complete(struct fhmci_host *host)
+{
+ unsigned int cmd_retry_count = 0;
+ unsigned long cmd_jiffies_timeout;
+ unsigned int cmd_irq_reg = 0;
+ unsigned long flags;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+
+ cmd_jiffies_timeout = jiffies + request_timeout;
+ while (1) {
+
+ do {
+ spin_lock_irqsave(&host->lock, flags);
+ cmd_irq_reg = readl(host->base + MCI_RINTSTS);
+ if (cmd_irq_reg & ACD_INT_STATUS) {
+ fhmci_writel((ACD_INT_STATUS | RTO_INT_STATUS
+ | RCRC_INT_STATUS | RE_INT_STATUS),
+ host->base + MCI_RINTSTS);
+ spin_unlock_irqrestore(&host->lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+ cmd_retry_count++;
+ } while (cmd_retry_count < retry_count);
+
+ cmd_retry_count = 0;
+ if (host->card_status == CARD_UNPLUGED)
+ return -1;
+
+ if (!time_before(jiffies, cmd_jiffies_timeout)) {
+ fhmci_trace(3, "wait auto stop complete is timeout!");
+ return -1;
+ }
+
+ schedule();
+ }
+
+}
+#endif
+static int fh_mci_wait_data_complete(struct fhmci_host *host)
+{
+ unsigned int tmp_reg;
+ struct mmc_data *data = host->data;
+ long time = request_timeout;
+ unsigned long flags;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ fhmci_assert(data);
+
+ time = wait_event_timeout(host->intr_wait,
+ test_bit(FHMCI_PEND_DTO_b, &host->pending_events),
+ time);
+
+ /* Mask MMC host data intr */
+ spin_lock_irqsave(&host->lock, flags);
+ tmp_reg = fhmci_readl(host->base + MCI_INTMASK);
+ tmp_reg &= ~DATA_INT_MASK;
+ fhmci_writel(tmp_reg, host->base + MCI_INTMASK);
+ host->pending_events &= ~FHMCI_PEND_DTO_m;
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ if (((time <= 0)
+ && (!test_bit(FHMCI_PEND_DTO_b, &host->pending_events)))
+ || (host->card_status == CARD_UNPLUGED)) {
+
+ data->error = -ETIMEDOUT;
+ fhmci_trace(3, "wait data request complete is timeout! 0x%08X",
+ host->irq_status);
+ fh_mci_idma_stop(host);
+ fh_mci_data_done(host, host->irq_status);
+ return -1;
+ }
+
+ fh_mci_idma_stop(host);
+ fh_mci_data_done(host, host->irq_status);
+ return 0;
+}
+
+
+static int fh_mci_wait_card_complete(struct fhmci_host *host,
+ struct mmc_data *data)
+{
+ unsigned int card_retry_count = 0;
+ unsigned long card_jiffies_timeout;
+ unsigned int card_status_reg = 0;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(host);
+ /* fhmci_assert(data); */
+
+ card_jiffies_timeout = jiffies + FH_MCI_DETECT_TIMEOUT;
+ while (1) {
+
+ do {
+ card_status_reg = readl(host->base + MCI_STATUS);
+ if (!(card_status_reg & DATA_BUSY)) {
+ fhmci_trace(2, "end");
+ return 0;
+ }
+ card_retry_count++;
+ } while (card_retry_count < retry_count);
+ card_retry_count = 0;
+
+ if (host->card_status == CARD_UNPLUGED) {
+ data->error = -ETIMEDOUT;
+ return -1;
+ }
+
+ if (!time_before(jiffies, card_jiffies_timeout)) {
+ if (data != NULL)
+ data->error = -ETIMEDOUT;
+ fhmci_trace(3, "wait card ready complete is timeout!");
+ return -1;
+ }
+
+ schedule();
+ }
+}
+
+static unsigned long t = 0;
+static unsigned long cmds = 0;
+static unsigned long long send_byte_count = 0;
+static struct timeval in_cmd, out_cmd;
+static struct timeval *x = &out_cmd, *y = &in_cmd;
+static unsigned long max = 0, sum = 0;
+static unsigned long called = 0, ended = 0;
+
+static void fh_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ struct fhmci_host *host = mmc_priv(mmc);
+ int byte_cnt = 0;
+ #ifdef CONFIG_SEND_AUTO_STOP
+ int trans_cnt;
+ #endif
+ int fifo_count = 0, tmp_reg;
+ int ret = 0;
+ unsigned long flags;
+
+ if (host->id == 1) {
+ called++;
+ memset(x, 0, sizeof(struct timeval));
+ memset(y, 0, sizeof(struct timeval));
+ do_gettimeofday(y);
+ }
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(mmc);
+ fhmci_assert(mrq);
+ fhmci_assert(host);
+
+ host->mrq = mrq;
+ host->irq_status = 0;
+
+
+ if (host->card_status == CARD_UNPLUGED) {
+ mrq->cmd->error = -ENODEV;
+ goto request_end;
+ }
+#if 1
+ ret = fh_mci_wait_card_complete(host, mrq->data);
+
+ if (ret) {
+ mrq->cmd->error = ret;
+ goto request_end;
+ }
+#endif
+ /* prepare data */
+ if (mrq->data) {
+ ret = fh_mci_setup_data(host, mrq->data);
+ if (ret) {
+ mrq->data->error = ret;
+ fhmci_trace(3, "data setup is error!");
+ goto request_end;
+ }
+
+ byte_cnt = mrq->data->blksz * mrq->data->blocks;
+ fhmci_writel(byte_cnt, host->base + MCI_BYTCNT);
+ fhmci_writel(mrq->data->blksz, host->base + MCI_BLKSIZ);
+
+ tmp_reg = fhmci_readl(host->base + MCI_CTRL);
+ tmp_reg |= FIFO_RESET;
+ fhmci_writel(tmp_reg, host->base + MCI_CTRL);
+
+ do {
+ tmp_reg = fhmci_readl(host->base + MCI_CTRL);
+ fifo_count++;
+ if (fifo_count >= retry_count) {
+ printk(KERN_INFO "fifo reset is timeout!");
+ return;
+ }
+ } while (tmp_reg&FIFO_RESET);
+
+ /* start DMA */
+ fh_mci_idma_start(host);
+ } else {
+ fhmci_writel(0, host->base + MCI_BYTCNT);
+ fhmci_writel(0, host->base + MCI_BLKSIZ);
+ }
+
+ /* send command */
+ ret = fh_mci_exec_cmd(host, mrq->cmd, mrq->data);
+ if (ret) {
+ mrq->cmd->error = ret;
+ fh_mci_idma_stop(host);
+ fhmci_trace(3, "can't send card cmd! ret = %d", ret);
+ goto request_end;
+ }
+
+ /* wait command send complete */
+ ret = fh_mci_wait_cmd_complete(host);
+
+ /* start data transfer */
+ if (mrq->data) {
+ if (!(mrq->cmd->error)) {
+ /* Open MMC host data intr */
+ spin_lock_irqsave(&host->lock, flags);
+ tmp_reg = fhmci_readl(host->base + MCI_INTMASK);
+ tmp_reg |= DATA_INT_MASK;
+ fhmci_writel(tmp_reg, host->base + MCI_INTMASK);
+ spin_unlock_irqrestore(&host->lock, flags);
+ /* wait data transfer complete */
+ ret = fh_mci_wait_data_complete(host);
+ } else {
+ /* CMD error in data command */
+ fh_mci_idma_stop(host);
+ }
+
+ if (mrq->stop) {
+#ifdef CONFIG_SEND_AUTO_STOP
+ trans_cnt = fhmci_readl(host->base + MCI_TCBCNT);
+ /* send auto stop */
+ if ((trans_cnt == byte_cnt) && (!(host->is_tuning))) {
+ fhmci_trace(3, "byte_cnt = %d, trans_cnt = %d",
+ byte_cnt, trans_cnt);
+ ret = fh_mci_wait_auto_stop_complete(host);
+ if (ret) {
+ mrq->stop->error = -ETIMEDOUT;
+ goto request_end;
+ }
+ } else {
+#endif
+ /* send soft stop command */
+ fhmci_trace(3, "this time, send soft stop");
+ ret = fh_mci_exec_cmd(host, host->mrq->stop,
+ host->data);
+ if (ret) {
+ mrq->stop->error = ret;
+ goto request_end;
+ }
+ ret = fh_mci_wait_cmd_complete(host);
+ if (ret)
+ goto request_end;
+#ifdef CONFIG_SEND_AUTO_STOP
+ }
+#endif
+ }
+ }
+
+request_end:
+ /* clear MMC host intr */
+ spin_lock_irqsave(&host->lock, flags);
+ fhmci_writel(ALL_INT_CLR & (~SDIO_INT_STATUS),
+ host->base + MCI_RINTSTS);
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ fh_mci_finish_request(host, mrq);
+
+
+ if (host->id == 1) {
+ ended++;
+ do_gettimeofday(x);
+
+ /* Perform the carry for the later subtraction by updating y. */
+ if (x->tv_usec < y->tv_usec) {
+ int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+
+ y->tv_usec -= 1000000 * nsec;
+ y->tv_sec += nsec;
+ }
+ if (x->tv_usec - y->tv_usec > 1000000) {
+ int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+
+ y->tv_usec += 1000000 * nsec;
+ y->tv_sec -= nsec;
+ }
+ /* Compute the time remaining to wait.
+ * tv_usec is certainly positive.
+ */
+ if (((x->tv_sec - y->tv_sec) * 1000
+ + x->tv_usec - y->tv_usec) > max) {
+ max = (x->tv_sec - y->tv_sec)
+ * 1000 + x->tv_usec - y->tv_usec;
+ }
+
+ sum += (x->tv_sec - y->tv_sec) * 1000 + x->tv_usec - y->tv_usec;
+
+ send_byte_count += byte_cnt;
+ cmds++;
+
+ if (jiffies - t > HZ) {
+ /*
+ * pr_info("SDIO HOST send_byte_count:
+ * %llu in %u cmds, max cost time: %lu,
+ * sum: %lu, ave: %lu\ncalled: %lu, ended: %lu\n",
+ * send_byte_count, cmds, max, sum,
+ * sum / cmds, called, ended);
+ */
+ t = jiffies;
+ send_byte_count = 0;
+ cmds = 0;
+ max = 0;
+ sum = 0;
+ called = 0;
+ ended = 0;
+ }
+ }
+}
+
+#ifdef FH_SDIO30
+static int fhmci_send_stop(struct mmc_host *host)
+{
+ struct mmc_command cmd = {0};
+ int err;
+
+ cmd.opcode = MMC_STOP_TRANSMISSION;
+ cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+ err = mmc_wait_for_cmd(host, &cmd, 0);
+ return err;
+}
+
+
+/*
+ * The procedure of tuning the phase shift of sampling clock
+ *
+ * 1.Set a phase shift of 0° on cclk_in_sample
+ * 2.Send the Tuning command to the card
+ * 3.increase the phase shift value of cclk_in_sample until the
+ * correct sampling point is received such that the host does not
+ * see any of the errors.
+ * 4.Mark this phase shift value as the starting point of the sampling
+ * window.
+ * 5.increase the phase shift value of cclk_in_sample until the host
+ * sees the errors starting to come again or the phase shift value
+ * reaches 360°.
+ * 6.Mark the last successful phase shift value as the ending
+ * point of the sampling window.
+ *
+ * A window is established where the tuning block is matched.
+ * For example, for a scenario where the tuning block is received
+ * correctly for a phase shift window of 90°and 180°, then an appropriate
+ * sampling point is established as 135°. Once a sampling point is
+ * established, no errors should be visible in the tuning block.
+ *
+ */
+
+static int fhmci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+ struct fhmci_host *host;
+ unsigned long flags;
+ unsigned int index, count;
+ unsigned int err = 0;
+ unsigned int found = 0; /* identify if we have found a valid phase */
+ unsigned int reg_value;
+ unsigned int start_point;
+ unsigned int end_point;
+ unsigned int prev_err = NOT_FOUND;
+ unsigned int raise_point = NOT_FOUND;
+ unsigned int fall_point = NOT_FOUND;
+ int phase;
+
+ struct mmc_command cmd = {0};
+ struct mmc_request mrq = {NULL};
+ struct mmc_data data = {0};
+
+ u32 cmd_opcode = opcode;
+ struct tuning_blk_info tuning_info = {NULL, 0};
+ struct scatterlist sg;
+ void *data_buf;
+
+ switch (cmd_opcode) {
+ case MMC_SEND_TUNING_BLOCK_HS200:
+ if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
+ tuning_info.blk = (u8 *)tuning_blk_8bit;
+ tuning_info.blk_size = sizeof(tuning_blk_8bit);
+ } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
+ tuning_info.blk = (u8 *)tuning_blk_4bit;
+ tuning_info.blk_size = sizeof(tuning_blk_4bit);
+ }
+ break;
+
+ case MMC_SEND_TUNING_BLOCK:
+ tuning_info.blk = (u8 *)tuning_blk_4bit;
+ tuning_info.blk_size = sizeof(tuning_blk_4bit);
+ break;
+ case MMC_SWITCH:
+ tuning_info.blk = (u8 *)tuning_blk_4bit;
+ tuning_info.blk_size = sizeof(tuning_blk_4bit);
+ break;
+ case MMC_SEND_EXT_CSD:
+ tuning_info.blk_size = 512;
+ break;
+ default:
+ fhmci_trace(3, "command %d not support", cmd_opcode);
+ return -EINVAL;
+ }
+
+ fhmci_trace(3, "command %d send", cmd_opcode);
+
+ data_buf = kmalloc(tuning_info.blk_size, GFP_KERNEL);
+ memset(data_buf, 0, tuning_info.blk_size);
+ if (data_buf == NULL)
+ return -ENOMEM;
+
+ sg_init_one(&sg, data_buf, tuning_info.blk_size);
+
+ host = mmc_priv(mmc);
+
+ fhmci_trace(3, "start sd3.0 phase tuning...");
+
+ if (cmd_opcode == MMC_SEND_EXT_CSD) {
+ start_point = HS400_TUNING_START_PHASE;
+ end_point = HS400_TUNING_END_PHASE;
+ } else {
+ start_point = TUNING_START_PHASE;
+ end_point = TUNING_END_PHASE;
+ }
+ for (index = start_point; index <= end_point; index++) {
+
+ /* Construct mmc_request */
+ cmd.opcode = cmd_opcode;
+ cmd.arg = 0;
+ cmd.retries = 0;
+ cmd.data = NULL;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+ cmd.error = 0;
+ data.error = 0;
+
+ mrq.data = &data;
+ mrq.data->blksz = tuning_info.blk_size;
+ mrq.data->blocks = 1;
+ mrq.data->flags = MMC_DATA_READ;
+ mrq.data->sg = &sg;
+ mrq.data->sg_len = 1;
+ mrq.stop = NULL;
+ mrq.cmd = &cmd;
+
+ host->mrq = &mrq;
+
+ /* set sample clk phase shift */
+ spin_lock_irqsave(&host->lock, flags);
+
+ reg_value = fhmci_readl(host->base + MCI_UHS_REG);
+ reg_value &= ~CLK_SMPL_PHS_MASK;
+ reg_value |= (index << 16);
+ fhmci_writel(reg_value, host->base + MCI_UHS_REG);
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ count = 0;
+ do {
+ cmd.error = 0;
+ data.error = 0;
+ memset(data_buf, 0, tuning_info.blk_size);
+ mmc_wait_for_req(mmc, &mrq);
+ if (cmd_opcode != MMC_SEND_EXT_CSD)
+ fhmci_send_stop(mmc); /* send soft_stop tail */
+ if ((cmd.error) || (data.error)) {
+ fhmci_trace(3, "cmd.error=%d data.error=%d",
+ cmd.error, data.error);
+ err = 1;
+ break;
+ } else {
+ if (cmd_opcode != MMC_SEND_EXT_CSD)
+ if (memcmp(tuning_info.blk, data_buf,
+ tuning_info.blk_size)) {
+ fhmci_trace(3,
+ "tuning blk not same!");
+ err = 1;
+ break;
+ }
+ }
+ count++;
+ } while (count < 1);
+
+ if (!err) {
+ /* found first valid phase */
+ found = 1;
+ }
+ if (index > start_point) {
+ if (err && !prev_err)
+ fall_point = index - 1;
+
+ if (!err && prev_err)
+ raise_point = index;
+ }
+
+ if ((raise_point != NOT_FOUND) && (fall_point != NOT_FOUND))
+ goto tuning_out;
+
+ prev_err = err;
+ err = 0;
+ }
+
+tuning_out:
+ kfree(data_buf);
+
+ if (!found) {
+ fhmci_trace(5, "%s: no valid phase shift! use default",
+ mmc_hostname(mmc));
+ fhmci_writel(DEFAULT_PHASE, host->base + MCI_UHS_REG);
+ } else {
+ fhmci_trace(3, "Tuning finished!!");
+
+ if (NOT_FOUND == raise_point)
+ raise_point = start_point;
+ if (NOT_FOUND == fall_point)
+ fall_point = end_point;
+
+ if (fall_point < raise_point) {
+ phase = (raise_point + fall_point) / 2;
+ phase = phase - (HIMCI_PHASE_SCALE / 2);
+ phase = (phase < 0) ? (HIMCI_PHASE_SCALE + phase) : phase;
+ } else
+ phase = (raise_point + fall_point) / 2;
+
+ spin_lock_irqsave(&host->lock, flags);
+ reg_value = fhmci_readl(host->base + MCI_UHS_REG);
+ reg_value &= ~CLK_SMPL_PHS_MASK;
+ reg_value |= (phase << 16);
+ fhmci_writel(reg_value, host->base + MCI_UHS_REG);
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ pr_info("%stuning %s: valid phase shift [%d, %d] Final Phase %d\n",
+ (cmd_opcode == MMC_SEND_EXT_CSD) ? "HS400 " : "",
+ mmc_hostname(mmc),
+ raise_point, fall_point, phase);
+ }
+
+ return 0;
+}
+#endif
+
+static void fh_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct fhmci_host *host = mmc_priv(mmc);
+ unsigned int tmp_reg;
+ u32 ctrl;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(mmc);
+ fhmci_assert(ios);
+ fhmci_assert(host);
+
+ fhmci_trace(3, "ios->power_mode = %d ", ios->power_mode);
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ /*
+ * Set controller working voltage as 3.3V before power off.
+ */
+ ctrl = fhmci_readl(host->base + MCI_UHS_REG);
+ ctrl &= ~FH_SDXC_CTRL_VDD_180;
+ fhmci_trace(3, "set voltage %d[addr 0x%x]", ctrl, MCI_UHS_REG);
+ fhmci_writel(ctrl, host->base + MCI_UHS_REG);
+
+ fh_mci_ctrl_power(host, POWER_OFF);
+ break;
+ case MMC_POWER_UP:
+ case MMC_POWER_ON:
+ fh_mci_ctrl_power(host, POWER_ON);
+ break;
+ }
+ fhmci_trace(3, "ios->clock = %d ", ios->clock);
+ if (ios->clock) {
+
+ fh_mci_control_cclk(host, DISABLE);
+ fh_mci_set_cclk(host, ios->clock);
+ fh_mci_control_cclk(host, ENABLE);
+
+ /* speed mode check ,if it is DDR50 set DDR mode*/
+ if ((ios->timing == MMC_TIMING_UHS_DDR50)) {
+ ctrl = fhmci_readl(host->base + MCI_UHS_REG);
+ if (!(FH_SDXC_CTRL_DDR_REG & ctrl)) {
+ ctrl |= FH_SDXC_CTRL_DDR_REG;
+ fhmci_writel(ctrl, host->base + MCI_UHS_REG);
+ }
+ }
+ } else {
+ fh_mci_control_cclk(host, DISABLE);
+ if ((ios->timing != MMC_TIMING_UHS_DDR50)) {
+ ctrl = fhmci_readl(host->base + MCI_UHS_REG);
+ if (FH_SDXC_CTRL_DDR_REG & ctrl) {
+ ctrl &= ~FH_SDXC_CTRL_DDR_REG;
+ fhmci_writel(ctrl, host->base + MCI_UHS_REG);
+ }
+ }
+ }
+
+ /* set bus_width */
+ fhmci_trace(3, "ios->bus_width = %d ", ios->bus_width);
+ if (ios->bus_width == MMC_BUS_WIDTH_4) {
+ tmp_reg = fhmci_readl(host->base + MCI_CTYPE);
+ tmp_reg |= CARD_WIDTH;
+ fhmci_writel(tmp_reg, host->base + MCI_CTYPE);
+ } else {
+ tmp_reg = fhmci_readl(host->base + MCI_CTYPE);
+ tmp_reg &= ~CARD_WIDTH;
+ fhmci_writel(tmp_reg, host->base + MCI_CTYPE);
+ }
+}
+
+static void fhmci_enable_sdio_irq(struct mmc_host *host, int enable)
+{
+ struct fhmci_host *fh_host = mmc_priv(host);
+ unsigned int reg_value;
+ unsigned long flags;
+
+ if (enable) {
+ local_irq_save(flags);
+
+ reg_value = fhmci_readl(fh_host->base + MCI_INTMASK);
+ reg_value |= 0x10000;
+ fhmci_writel(reg_value, fh_host->base + MCI_INTMASK);
+ local_irq_restore(flags);
+ } else {
+ reg_value = fhmci_readl(fh_host->base + MCI_INTMASK);
+ reg_value &= ~0xffff0000;
+ fhmci_writel(reg_value, fh_host->base + MCI_INTMASK);
+ }
+
+}
+
+
+static int fh_mci_get_ro(struct mmc_host *mmc)
+{
+ unsigned int ret;
+ struct fhmci_host *host = mmc_priv(mmc);
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(mmc);
+
+ ret = host->get_ro(host);
+
+ return ret;
+}
+
+/**
+ * @brief get the status of SD card's CD pin
+ *
+ * @param [in] mmc host struct
+ *
+ * @return "1": sd card in the slot, "0": sd card is not in the slot, "2":status of sd card no changed
+ */
+static int fh_mci_get_cd(struct mmc_host *mmc)
+{
+ unsigned int i, curr_status, status[3] = {0}, detect_retry_count = 0;
+ struct fhmci_host *host = mmc_priv(mmc);
+
+ while (1) {
+ for (i = 0; i < 3; i++) {
+ status[i] = host->get_cd(host);
+ udelay(10);
+ }
+ if ((status[0] == status[1]) && (status[0] == status[2]))
+ break;
+
+ detect_retry_count++;
+ if (detect_retry_count >= retry_count) {
+ fhmci_error("this is a dithering,card detect error!");
+ goto err;
+ }
+ }
+ curr_status = status[0];
+ if (curr_status != host->card_status) {
+ host->card_status = curr_status;
+ if (curr_status != CARD_UNPLUGED) {
+ fh_mci_init_card(host);
+ printk(KERN_INFO "card%d connected!\n", host->id);
+ mmc->rescan_count = 0;
+ return 1;
+ } else {
+ printk(KERN_INFO "card%d disconnected!\n", host->id);
+ return 0;
+ }
+ }
+ if (mmc->card == NULL)
+ fh_mci_init_card(host);
+
+ /*if card status is always disconnect dont poll*/
+ if (host->card_status == CARD_UNPLUGED)
+ return 0;
+err:
+ return 2;
+}
+#ifdef FH_SDIO30
+static int fhmci_switch_sdio_vol(struct mmc_host *mmc, struct mmc_ios *ios)
+ {
+ struct fhmci_host *host = mmc_priv(mmc);
+ u32 ctrl;
+
+ /*
+ * We first check whether the request is to
+ * set signalling voltage to 3.3V. If so,
+ *we change the voltage to 3.3V and return quickly.
+ */
+ ctrl = fhmci_readl(host->base + MCI_UHS_REG);
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
+ /* Set 1.8V Signal Enable in the MCI_UHS_REG to 1 */
+ fhmci_trace(3, "switch voltage 330");
+ ctrl &= ~(FH_SDXC_CTRL_VDD_180);
+ fhmci_writel(ctrl, host->base + MCI_UHS_REG);
+
+ /* Wait for 5ms */
+ usleep_range(5000, 5500);
+
+ /* 3.3V regulator output should be stable within 5ms */
+ ctrl = fhmci_readl(host->base + MCI_UHS_REG);
+ if (!(ctrl & (FH_SDXC_CTRL_VDD_180))) {
+ /* config Pin drive capability */
+ return 0;
+ } else {
+ fhmci_error(": Switching to 3.3V ");
+ fhmci_error("signalling voltage failed\n");
+ return -EIO;
+ }
+ } else if (!(ctrl & (FH_SDXC_CTRL_VDD_180)) &&
+ (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) {
+ /* Stop SDCLK */
+ fhmci_trace(3, "switch voltage 180");
+ fh_mci_control_cclk(host, DISABLE);
+
+ /*
+ * Enable 1.8V Signal Enable in the MCI_UHS_REG
+ */
+ ctrl |= (FH_SDXC_CTRL_VDD_180);
+ fhmci_writel(ctrl, host->base + MCI_UHS_REG);
+
+ /* Wait for 8ms */
+ usleep_range(8000, 8500);
+
+ ctrl = fhmci_readl(host->base + MCI_UHS_REG);
+ if (ctrl & (FH_SDXC_CTRL_VDD_180)) {
+ /* Provide SDCLK again and wait for 1ms */
+ fh_mci_control_cclk(host, ENABLE);
+ usleep_range(1000, 1500);
+
+ if (mmc->caps2 & MMC_CAP2_HS200) {
+ /* eMMC needn't to check the int status*/
+ return 0;
+ }
+ /*
+ * If CMD11 return CMD down, then the card
+ * was successfully switched to 1.8V signaling.
+ */
+ ctrl = fhmci_readl(host->base + MCI_RINTSTS);
+ while (!((ctrl & VOLT_SWITCH_INT_STATUS)
+ && (ctrl & CD_INT_STATUS)))
+ ctrl = fhmci_readl(host->base + MCI_RINTSTS);
+
+
+ {
+ /* config Pin drive capability */
+ /*printk("@@@@@VOLT_SWITCH_INT_STATUS\n");*/
+ fhmci_writel(VOLT_SWITCH_INT_STATUS | CD_INT_STATUS,
+ host->base + MCI_RINTSTS);
+ return 0;
+ }
+ }
+
+ /*
+ * If we are here, that means the switch to 1.8V signaling
+ * failed. We power cycle the card, and retry initialization
+ * sequence by setting S18R to 0.
+ */
+
+ ctrl &= ~(FH_SDXC_CTRL_VDD_180);
+ fhmci_writel(ctrl, host->base + MCI_UHS_REG);
+
+ /* Wait for 5ms */
+ usleep_range(5000, 5500);
+
+ fh_mci_ctrl_power(host, POWER_OFF);
+ /* Wait for 1ms as per the spec */
+ usleep_range(1000, 1500);
+ fh_mci_ctrl_power(host, POWER_ON);
+
+ fh_mci_control_cclk(host, DISABLE);
+ /* Wait for 1ms as per the spec */
+ usleep_range(1000, 1500);
+ fh_mci_control_cclk(host, ENABLE);
+
+ fhmci_error(": Switching to 1.8V signalling ");
+ fhmci_error("voltage failed, retrying with S18R set to 0\n");
+ return -EAGAIN;
+ } else
+ /* No signal voltage switch required */
+ return 0;
+ }
+#endif
+
+
+static const struct mmc_host_ops fh_mci_ops = {
+ .request = fh_mci_request,
+ .set_ios = fh_mci_set_ios,
+ .get_ro = fh_mci_get_ro,
+ .enable_sdio_irq = fhmci_enable_sdio_irq,
+ .get_cd = fh_mci_get_cd,
+ /*.start_signal_voltage_switch = fhmci_switch_sdio_vol,*/
+ /*.execute_tuning = fhmci_execute_tuning,*/
+};
+
+static irqreturn_t hisd_irq(int irq, void *dev_id)
+{
+ struct fhmci_host *host = dev_id;
+ u32 state = 0;
+ int handle = 0;
+
+ state = fhmci_readl(host->base + MCI_RINTSTS);
+#ifndef CONFIG_SEND_AUTO_STOP
+ /*
+ * bugfix: when send soft stop to SD Card, Host will report
+ * sdio interrupt, This situation needs to be avoided
+ */
+ if ((host->mmc->card != NULL)
+ && (host->mmc->card->type == MMC_TYPE_SDIO)) {
+#endif
+ if (state & SDIO_INT_STATUS) {
+ if (fhmci_readl(host->base + MCI_INTMASK) & SDIO_INT_STATUS) {
+ fhmci_writel(SDIO_INT_STATUS, host->base + MCI_RINTSTS);
+ mmc_signal_sdio_irq(host->mmc);
+ handle = 1;
+ }
+ }
+#ifndef CONFIG_SEND_AUTO_STOP
+ }
+#endif
+
+ if (state & DATA_INT_MASK) {
+ handle = 1;
+ host->pending_events |= FHMCI_PEND_DTO_m;
+
+ host->irq_status = fhmci_readl(host->base + MCI_RINTSTS);
+ if (host->irq_status & (DCRC_INT_STATUS|SBE_INT_STATUS|EBE_INT_STATUS)) {
+#ifndef CONFIG_MACH_FH8830_FPGA
+ printk(KERN_ERR "SDC CRC error:%08x,.\n",
+ host->irq_status);
+#endif
+ }
+ fhmci_writel(DATA_INT_MASK, host->base + MCI_RINTSTS);
+ wake_up(&host->intr_wait);
+ }
+
+ /*if (state & 0x10000) {
+ * handle = 1;
+ * fhmci_writel(0x10000, host->base + MCI_RINTSTS);
+ * mmc_signal_sdio_irq(host->mmc);
+ * }
+ */
+
+ if (handle)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
+}
+#ifdef CONFIG_USE_OF
+static unsigned int fh_mci_sys_card_detect_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+static unsigned int fh_mci_sys_read_only_fixed(struct fhmci_host *host)
+{
+ return 0;
+}
+#endif
+static int sd_init(struct fhmci_host *host,
+ unsigned int drv_degree, unsigned int sam_degree)
+{
+ u32 slot_id = host->id;
+ struct clk *sdc_clk;
+ struct clk *sdc_clk_drv;
+ struct clk *sdc_clk_sample;
+ char name[32];
+
+ sprintf(name, "sdc%d_clk", slot_id);
+ sdc_clk = clk_get(NULL, name);
+ clk_prepare_enable(sdc_clk);
+
+ fh_pmu_sdc_reset(slot_id);
+
+ clk_set_rate(sdc_clk, 50000000);
+ sprintf(name, "sdc%d_clk_sample", slot_id);
+ sdc_clk_sample = clk_get(NULL, name);
+ clk_set_phase(sdc_clk_sample, sam_degree);
+
+ sprintf(name, "sdc%d_clk_drv", slot_id);
+ sdc_clk_drv = clk_get(NULL, name);
+ clk_set_phase(sdc_clk_drv, drv_degree);
+ return 0;
+}
+
+static int fh_mci_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct fhmci_host *host = NULL;
+ int ret = 0, irq;
+ u32 id = 0xffffffff;
+ u32 drv_degree = 0;
+ u32 sam_degree = 0;
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+ u32 bus_width = 0;
+ u32 wp_flag = 0xffffffff;
+ u32 cd_flag = 0xffffffff;
+ u32 scan_mux = 0xffffffff;
+#else
+ struct resource *regs;
+#endif
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(pdev);
+
+ mmc = mmc_alloc_host(sizeof(struct fhmci_host), &pdev->dev);
+ if (!mmc) {
+ fhmci_error("no mem for hi mci host controller!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+ host = mmc_priv(mmc);
+ host->card_status = 0xffffffff;
+ host->bus_hz = 50000000;
+ /*host->pdata = pdev->dev.platform_data;*/
+ mmc->ops = &fh_mci_ops;
+ mmc->rescan_disable = FALSE;
+ mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
+ mmc->f_max = host->bus_hz;
+
+ mmc->caps = MMC_CAP_SD_HIGHSPEED
+ | MMC_CAP_MMC_HIGHSPEED
+ | MMC_CAP_NEEDS_POLL
+ |MMC_CAP_SDIO_IRQ; //MC_CAP_UHS_SDR25;
+
+ mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
+ mmc->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
+#ifdef CONFIG_USE_OF
+ of_property_read_u32(np, "buswidth", &bus_width);
+ of_property_read_u32(np, "id", &id);
+ of_property_read_u32(np, "drv-degree", &drv_degree);
+ of_property_read_u32(np, "sam-degree", &sam_degree);
+ of_property_read_u32(np, "cd-fixed", &cd_flag);
+ of_property_read_u32(np, "wp-fixed", &wp_flag);
+ of_property_read_u32(np, "scan-mux", &scan_mux);
+
+ mmc->rescan_max_num = scan_mux;
+ if (bus_width == 4)
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+ if (cd_flag == 1)
+ host->get_cd = fh_mci_sys_card_detect_fixed;
+ else if (cd_flag == 0)
+ host->get_cd = fh_mci_sys_card_detect;
+ else
+ pr_err("fh_mci_probe cd-fixed value error\n");
+
+ if (wp_flag == 1)
+ host->get_ro = fh_mci_sys_read_only_fixed;
+ else if (wp_flag == 0)
+ host->get_ro = fh_mci_ctrl_card_readonly;
+ else
+ pr_err("fh_mci_probe wp-fixed value error\n");
+
+
+ host->base = of_iomap(np, 0);
+ if (!host->base) {
+ fhmci_error("no mem for fhmci base!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq < 0) {
+ printk(KERN_ERR "no IRQ defined!\n");
+ goto out;
+ }
+
+#else
+ host->pdata = pdev->dev.platform_data;
+
+ mmc->caps |= host->pdata->caps;
+ id = pdev->id;
+ drv_degree = host->pdata->drv_degree;
+ sam_degree = host->pdata->sam_degree;
+ mmc->rescan_max_num = host->pdata->rescan_max_num;
+
+ if (host->pdata->get_cd)
+ host->get_cd = host->pdata->get_cd;
+ else
+ host->get_cd = fh_mci_sys_card_detect;
+
+ if (host->pdata->get_ro)
+ host->get_ro = host->pdata->get_ro;
+ else
+ host->get_ro = fh_mci_ctrl_card_readonly;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ fhmci_error("request resource error!\n");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ host->base = ioremap_nocache(regs->start,
+ regs->end - regs->start + 1);
+ if (!host->base) {
+ fhmci_error("no mem for fhmci base!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ irq = irq_create_mapping(NULL, irq);
+ if (irq < 0) {
+ printk(KERN_ERR "no IRQ defined!\n");
+ goto out;
+ }
+#endif
+
+ /* reload by this controller */
+ mmc->max_blk_count = 2048;
+ mmc->max_segs = 64;
+ mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count;
+ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+ /*mmc->ocr = mmc->ocr_avail;*/
+
+ host->dma_vaddr = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+ &host->dma_paddr, GFP_KERNEL);
+ if (!host->dma_vaddr) {
+ fhmci_error("no mem for fhmci dma!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ host->mmc = mmc;
+ host->id = id;
+
+ sd_init(host, drv_degree, sam_degree);
+
+ /* config fifo depth */
+ host->fifo_depth = (fhmci_readl(host->base + MCI_FIFOTH) & 0xfff0000) >> 16;
+
+ fhmci_writel(SD_POWER_ON, host->base + MCI_PWREN);
+
+ /* enable card */
+ spin_lock_init(&host->lock);
+ platform_set_drvdata(pdev, mmc);
+
+ init_waitqueue_head(&host->intr_wait);
+
+ host->irq = irq;
+ snprintf(host->isr_name, sizeof(host->isr_name), "sdio-%d", id);
+ ret = request_irq(irq, hisd_irq, 0, host->isr_name, host);
+ if (ret) {
+ printk(KERN_ERR "request_irq error :%d!\n", ret);
+ goto out;
+ }
+
+ mmc_add_host(mmc);
+ return 0;
+out:
+ if (host) {
+
+ if (host->base)
+ iounmap(host->base);
+
+ if (host->dma_vaddr)
+ dma_free_coherent(&pdev->dev, PAGE_SIZE,
+ host->dma_vaddr, host->dma_paddr);
+ }
+ if (mmc)
+ mmc_free_host(mmc);
+
+ return ret;
+}
+
+/* for wifi Cypress 43438/43455
+ * (Note: sd_id is the sdio index used by wifi)
+ */
+void fh_sdio_card_scan(int sd_id)
+{
+ char name[32];
+ struct device_node *np;
+ struct platform_device *pdev = NULL;
+ struct mmc_host *mmc;
+ struct device *dev;
+
+ sprintf(name, "sdc%d", sd_id);
+ np = of_find_node_by_name(NULL, name);
+ if (np && !IS_ERR(np))
+ pdev = of_find_device_by_node(np);
+ else {
+ sprintf(name, "fh_mci.%d", sd_id);
+ dev = bus_find_device_by_name(&platform_bus_type, NULL, name);
+ if (dev && !IS_ERR(dev))
+ pdev = to_platform_device(dev);
+ else
+ pr_err("%s:%d, dev not found\n",
+ __func__, __LINE__);
+ }
+
+ if (!pdev) {
+ pr_err("%s:%d,device not found\n",
+ __func__, __LINE__);
+ return;
+ }
+ mmc = platform_get_drvdata(pdev);
+ if (!mmc) {
+ pr_err("%s:%d, drvdata not found\n",
+ __func__, __LINE__);
+ return;
+ }
+
+ mmc->caps &= ~MMC_CAP_NEEDS_POLL;
+ mmc->caps &= ~MMC_CAP_NONREMOVABLE;
+
+ mmc->rescan_count = 0;
+ mmc_detect_change(mmc, 0);
+ msleep(100);
+ mmc->caps |= MMC_CAP_NONREMOVABLE;
+
+}
+EXPORT_SYMBOL_GPL(fh_sdio_card_scan);
+
+static int fh_mci_remove(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (mmc) {
+ struct fhmci_host *host = mmc_priv(mmc);
+
+ free_irq(host->irq, host);
+ mmc_remove_host(mmc);
+ fh_mci_ctrl_power(host, POWER_OFF);
+ fh_mci_control_cclk(host, DISABLE);
+ iounmap(host->base);
+ dma_free_coherent(&pdev->dev, PAGE_SIZE, host->dma_vaddr,
+ host->dma_paddr);
+ mmc_free_host(mmc);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int fh_mci_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct fhmci_host *host;
+ int ret = 0;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(dev);
+
+ if (mmc) {
+ /*ret = mmc_suspend_host(mmc);*/
+
+ host = mmc_priv(mmc);
+ }
+
+ fhmci_trace(2, "end");
+
+ return ret;
+}
+
+static int fh_mci_resume(struct platform_device *dev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct fhmci_host *host;
+ int ret = 0;
+
+ fhmci_trace(2, "begin");
+ fhmci_assert(dev);
+
+ if (mmc) {
+ host = mmc_priv(mmc);
+ /* enable mmc clk */
+ /*fh_mci_sys_ctrl_init(host);*/
+ /* enable card */
+ fh_mci_init_card(host);
+
+ /*ret = mmc_resume_host(mmc);*/
+ }
+
+ fhmci_trace(2, "end");
+
+ return ret;
+}
+#else
+#define fh_mci_suspend NULL
+#define fh_mci_resume NULL
+#endif
+
+static const struct of_device_id fh_sdio_of_match[] = {
+ {.compatible = "fh,fh-sdc",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_sdio_of_match);
+
+static struct platform_driver fh_sdio_driver = {
+ .driver = {
+ .name = "fh_mci",
+ .of_match_table = fh_sdio_of_match,
+ },
+ .probe = fh_mci_probe,
+ .remove = fh_mci_remove,
+ .suspend = fh_mci_suspend,
+ .resume = fh_mci_resume,
+};
+
+static ssize_t fh_mci_rescan_control(struct class *cls,
+ struct class_attribute *attr, const char *_buf, size_t _count)
+{
+ int cmd = 0;
+ int err = 0;
+ char name[32];
+ struct device_node *np;
+ struct platform_device *pdev = NULL;
+ struct mmc_host *mmc;
+ struct device *dev;
+
+ err = kstrtoint(_buf, 10, &cmd);
+ if (err)
+ return _count;
+ sprintf(name, "sdc%d", cmd);
+ np = of_find_node_by_name(NULL, name);
+ if (np && !IS_ERR(np))
+ pdev = of_find_device_by_node(np);
+ else {
+ sprintf(name, "fh_mci.%d", cmd);
+ dev = bus_find_device_by_name(&platform_bus_type, NULL, name);
+ if (dev && !IS_ERR(dev))
+ pdev = to_platform_device(dev);
+ else
+ pr_err("%s:%d, dev not found\n",
+ __func__, __LINE__);
+ }
+ if (!pdev) {
+ pr_err("%s:%d,device %s not found\n",
+ __func__, __LINE__, np->name);
+ return -ENODEV;
+ }
+ mmc = platform_get_drvdata(pdev);
+ if (mmc)
+ mmc->rescan_count = 0;
+ else {
+ pr_err("%s:%d, drvdata not found\n",
+ __func__, __LINE__);
+ }
+ return _count;
+}
+
+
+static struct class *fhmci_rescan_class;
+
+static CLASS_ATTR(mmc_rescan, 0644, NULL, fh_mci_rescan_control);
+
+static void fh_mci_rescan_init(void)
+{
+ int err = 0;
+
+ fhmci_rescan_class = class_create(THIS_MODULE, "fhmci");
+ err = class_create_file(fhmci_rescan_class, &class_attr_mmc_rescan);
+ if (err)
+ fhmci_error("fhmci_rescan_class: create class file failed!");
+}
+
+static void fh_mci_rescan_exit(void)
+{
+ class_remove_file(fhmci_rescan_class, &class_attr_mmc_rescan);
+ class_destroy(fhmci_rescan_class);
+}
+
+static int __init fh_mci_init(void)
+{
+ int ret;
+
+ fhmci_trace(2, "mci init begin");
+ fh_mci_rescan_init();
+
+ ret = platform_driver_register(&fh_sdio_driver);
+ if (ret)
+ fhmci_error("Platform driver register is failed!");
+
+ return ret;
+}
+
+static void __exit fh_mci_exit(void)
+{
+ fh_mci_rescan_exit();
+ platform_driver_unregister(&fh_sdio_driver);
+}
+
+#ifdef CONFIG_DEFERRED_INIICALLS_MMC
+deferred_module_init(fh_mci_init);
+#else
+module_init(fh_mci_init);
+#endif
+module_exit(fh_mci_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("TANGYH");
+MODULE_DESCRIPTION("Fullhan SDIO device driver");
diff --git a/drivers/mmc/host/fhmci/fhmci_reg.h b/drivers/mmc/host/fhmci/fhmci_reg.h
new file mode 100644
index 00000000..121f76e1
--- /dev/null
+++ b/drivers/mmc/host/fhmci/fhmci_reg.h
@@ -0,0 +1,220 @@
+#ifndef _FH_MCI_REG_H_
+#define _FH_MCI_REG_H_
+
+#define MCI_CTRL 0x00
+#define MCI_PWREN 0x04
+#define MCI_CLKDIV 0x08
+#define MCI_CLKSRC 0x0C
+#define MCI_CLKENA 0x10
+#define MCI_TIMEOUT 0x14
+#define MCI_CTYPE 0x18
+#define MCI_BLKSIZ 0x1c
+#define MCI_BYTCNT 0x20
+#define MCI_INTMASK 0x24
+#define MCI_CMDARG 0x28
+#define MCI_CMD 0x2C
+#define MCI_RESP0 0x30
+#define MCI_RESP1 0x34
+#define MCI_RESP2 0x38
+#define MCI_RESP3 0x3C
+#define MCI_MINTSTS 0x40
+#define MCI_RINTSTS 0x44
+#define MCI_STATUS 0x48
+#define MCI_FIFOTH 0x4C
+#define MCI_CDETECT 0x50
+#define MCI_WRTPRT 0x54
+#define MCI_GPIO 0x58
+#define MCI_TCBCNT 0x5C
+#define MCI_TBBCNT 0x60
+#define MCI_DEBNCE 0x64
+#define MCI_USRID 0x68
+#define MCI_VERID 0x6C
+#define MCI_HCON 0x70
+#define MCI_UHS_REG 0x74
+#define MCI_BMOD 0x80
+#define MCI_DBADDR 0x88
+#define MCI_IDSTS 0x8C
+#define MCI_IDINTEN 0x90
+#define MCI_DSCADDR 0x94
+#define MCI_BUFADDR 0x98
+#define MCI_READ_THRESHOLD_SIZE 0x100
+#define MCI_UHS_EXT 0x108
+/* MCI_UHS_REG(0x74) details */
+#define HI_EMMC_CTRL_VDD_180 (0x2<<0)
+#define HI_EMMC_CTRL_DDR_REG (0x2<<16)
+#define FH_SDXC_CTRL_VDD_180 (1<<0)
+#define FH_SDXC_CTRL_DDR_REG (1<<16)
+
+/* MCI_BMOD(0x80) details */
+#define BMOD_SWR (1<<0)
+#define BURST_INCR (1<<1)
+#define BURST_8 (0x2<<8)
+
+/* MCI_CTRL(0x00) details */
+#define CTRL_RESET (1<<0)
+#define FIFO_RESET (1<<1)
+#define DMA_RESET (1<<2)
+#define INTR_EN (1<<4)
+#define USE_INTERNAL_DMA (1<<25)
+
+/* IDMAC DEST1 details */
+#define DMA_BUFFER 0x2000
+#define MAX_DMA_DES (20480)
+
+/* MCI_CDETECT(0x50) details */
+#define FHMCI_CARD0 (1<<0)
+
+/* MCI_TIMEOUT(0x14) details: */
+/*bit 31-8: data read timeout param*/
+#define DATA_TIMEOUT (0xffffff<<8)
+
+/* bit 7-0: response timeout param */
+#define RESPONSE_TIMEOUT 0xff
+
+/* bit 0: enable of card clk*/
+#define CCLK_ENABLE (1<<0)
+
+/* IDMAC DEST0 details */
+#define DMA_DES_OWN (1<<31)
+#define DMA_DES_NEXT_DES (1<<4)
+#define DMA_DES_FIRST_DES (1<<3)
+#define DMA_DES_LAST_DES (1<<2)
+
+/* MCI_BMOD(0x80) details */
+#define BMOD_DMA_EN (1<<7)
+
+/* MCI_CTYPE(0x18) details */
+#define CARD_WIDTH (0x1<<0)
+
+/* MCI_INTMASK(0x24) details:
+ bit 16-1: mask MMC host controller each interrupt
+*/
+#define ALL_INT_MASK 0x1ffff
+#define DTO_INT_MASK (1<<3)
+
+/* bit[18:16] sampling phase */
+#define CLK_SMPL_PHS_MASK (0x7F<<16)
+#define DEFAULT_PHASE 0x1050000
+
+
+/* MCI_CMD(0x2c) details:
+ bit 31: cmd execute or load start param of interface clk bit
+*/
+#define START_CMD (1<<31)
+
+
+/* MCI_INTSTS(0x44) details */
+/***************************************************************/
+/* bit 16: sdio interrupt status */
+#define SDIO_INT_STATUS (0x1<<16)
+
+/* bit 15: end-bit error (read)/write no CRC interrupt status */
+#define EBE_INT_STATUS (0x1<<15)
+
+/* bit 14: auto command done interrupt status */
+#define ACD_INT_STATUS (0x1<<14)
+
+/* bit 13: start bit error interrupt status */
+#define SBE_INT_STATUS (0x1<<13)
+
+/* bit 12: hardware locked write error interrupt status */
+#define HLE_INT_STATUS (0x1<<12)
+
+/* bit 11: FIFO underrun/overrun error interrupt status */
+#define FRUN_INT_STATUS (0x1<<11)
+
+/* bit 10: data starvation-by-host timeout interrupt status */
+#define HTO_INT_STATUS (0x1<<10)
+
+/* bit 10: volt_switch to 1.8v for sdxc */
+#define VOLT_SWITCH_INT_STATUS (0x1<<10)
+
+/* bit 9: data read timeout interrupt status */
+#define DRTO_INT_STATUS (0x1<<9)
+
+/* bit 8: response timeout interrupt status */
+#define RTO_INT_STATUS (0x1<<8)
+
+/* bit 7: data CRC error interrupt status */
+#define DCRC_INT_STATUS (0x1<<7)
+
+/* bit 6: response CRC error interrupt status */
+#define RCRC_INT_STATUS (0x1<<6)
+
+/* bit 5: receive FIFO data request interrupt status */
+#define RXDR_INT_STATUS (0x1<<5)
+
+/* bit 4: transmit FIFO data request interrupt status */
+#define TXDR_INT_STATUS (0x1<<4)
+
+/* bit 3: data transfer Over interrupt status */
+#define DTO_INT_STATUS (0x1<<3)
+
+/* bit 2: command done interrupt status */
+#define CD_INT_STATUS (0x1<<2)
+
+/* bit 1: response error interrupt status */
+#define RE_INT_STATUS (0x1<<1)
+#define DATA_INT_MASK (DTO_INT_STATUS | DCRC_INT_STATUS \
+ | SBE_INT_STATUS | EBE_INT_STATUS)
+/***************************************************************/
+
+/* MCI_RINTSTS(0x44) details:bit 16-1: clear
+ MMC host controller each interrupt but
+ hardware locked write error interrupt
+*/
+#define ALL_INT_CLR 0x1efff
+
+#define PHASE_SHIFT 0x1030000
+#define READ_THRESHOLD_SIZE 0x2000001
+
+/* MCI_STATUS(0x48) details */
+#define DATA_BUSY (0x1<<9)
+
+/* MCI_FIFOTH(0x4c) details */
+
+#define BURST_SIZE (0x2<<28)
+#define RX_WMARK (0x7<<16)
+#define TX_WMARK 0x8
+
+/* MCI_CARDTHRCTL(0x100) details */
+#define RW_THRESHOLD_SIZE (0x2000005)
+
+
+/*
+#define BURST_SIZE (0x6<<28)
+#define RX_WMARK (0x7f<<16)
+#define TX_WMARK 0x80
+*/
+
+
+union cmd_arg_s {
+ unsigned int cmd_arg;
+ struct cmd_bits_arg {
+ unsigned int cmd_index:6;
+ unsigned int response_expect:1;
+ unsigned int response_length:1;
+ unsigned int check_response_crc:1;
+ unsigned int data_transfer_expected:1;
+ unsigned int read_write:1;
+ unsigned int transfer_mode:1;
+ unsigned int send_auto_stop:1;
+ unsigned int wait_prvdata_complete:1;
+ unsigned int stop_abort_cmd:1;
+ unsigned int send_initialization:1;
+ unsigned int card_number:5;
+ unsigned int update_clk_reg_only:1; /* bit 21 */
+ unsigned int read_ceata_device:1;
+ unsigned int ccs_expected:1;
+ unsigned int enable_boot:1;
+ unsigned int expect_boot_ack:1;
+ unsigned int disable_boot:1;
+ unsigned int boot_mode:1;
+ unsigned int volt_switch:1;
+ unsigned int use_hold_reg:1;
+ unsigned int reserved:1;
+ unsigned int start_cmd:1; /* HSB */
+ } bits;
+};
+
+#endif
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index e83a279f..e364fae0 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -336,6 +336,8 @@ source "drivers/mtd/lpddr/Kconfig"
source "drivers/mtd/spi-nor/Kconfig"
+source "drivers/mtd/spi-nand/Kconfig"
+
source "drivers/mtd/ubi/Kconfig"
endif # MTD
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 99bb9a1f..581688f1 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -33,4 +33,5 @@ inftl-objs := inftlcore.o inftlmount.o
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
+obj-$(CONFIG_MTD_SPI_NAND) += spi-nand/
obj-$(CONFIG_MTD_UBI) += ubi/
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 16a7df2a..ecf7302e 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -34,6 +34,14 @@ struct m25p {
u8 command[MAX_CMD_SIZE];
};
+static void m25p80_scan_delay(struct spi_nor *nor)
+{
+ struct m25p *flash = nor->priv;
+ struct spi_device *spi = flash->spi;
+
+ spi->sample_delay++;
+}
+
static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
{
struct m25p *flash = nor->priv;
@@ -213,6 +221,7 @@ static int m25p_probe(struct spi_device *spi)
nor->write = m25p80_write;
nor->write_reg = m25p80_write_reg;
nor->read_reg = m25p80_read_reg;
+ nor->scan_delay = m25p80_scan_delay;
nor->dev = &spi->dev;
spi_nor_set_flash_node(nor, spi->dev.of_node);
@@ -226,8 +235,13 @@ static int m25p_probe(struct spi_device *spi)
else if (spi->mode & SPI_RX_DUAL)
mode = SPI_NOR_DUAL;
- if (data && data->name)
+ if (data && data->name) {
+ sprintf(data->name, "spi%d.%d",
+ spi->master->bus_num,
+ spi->chip_select);
+
nor->mtd.name = data->name;
+ }
/* For some (historical?) reason many platforms provide two different
* names in flash_platform_data: "name" and "type". Quite often name is
@@ -245,6 +259,9 @@ static int m25p_probe(struct spi_device *spi)
if (ret)
return ret;
+ if (nor->info->max_speed_hz)
+ spi->max_speed_hz = nor->info->max_speed_hz;
+
return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
data ? data->nr_parts : 0);
}
@@ -258,6 +275,13 @@ static int m25p_remove(struct spi_device *spi)
return mtd_device_unregister(&flash->spi_nor.mtd);
}
+static void m25p_shutdown(struct spi_device *spi)
+{
+ struct m25p *flash = spi_get_drvdata(spi);
+
+ spi_nor_restore(&flash->spi_nor);
+}
+
/*
* Do NOT add to this array without reading the following:
*
@@ -328,6 +352,7 @@ static struct spi_driver m25p80_driver = {
.id_table = m25p_ids,
.probe = m25p_probe,
.remove = m25p_remove,
+ .shutdown = m25p_shutdown,
/* REVISIT: many of these chips have deep power-down modes, which
* should clearly be entered on suspend() to minimize power use.
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 2af9869a..377d68bd 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -52,6 +52,8 @@ struct nand_flash_dev nand_flash_ids[] = {
{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
NAND_ECC_INFO(40, SZ_1K), 4 },
+ {"GD5F1GQ4UB", {.id = {0xD1, 0xc8,} }, SZ_2K, 128, SZ_128K, 0, 2, 128,
+ NAND_ECC_INFO(0, 0), 4 },
LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS),
LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
@@ -182,6 +184,8 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_SANDISK, "SanDisk"},
{NAND_MFR_INTEL, "Intel"},
{NAND_MFR_ATO, "ATO"},
+ {NAND_MFR_WINBOND, "WINBOND"},
+ {NAND_MFR_GD, "GD"},
{0x0, "Unknown"}
};
diff --git a/drivers/mtd/spi-nand/Kconfig b/drivers/mtd/spi-nand/Kconfig
new file mode 100644
index 00000000..b4da8f5b
--- /dev/null
+++ b/drivers/mtd/spi-nand/Kconfig
@@ -0,0 +1,7 @@
+menuconfig MTD_SPI_NAND
+ tristate "SPI-NAND device Support"
+ depends on MTD_NAND && SPI
+ help
+ This is the framework for the SPI NAND which can be used by the SPI
+ device drivers and the SPI-NAND device drivers.
+
diff --git a/drivers/mtd/spi-nand/Makefile b/drivers/mtd/spi-nand/Makefile
new file mode 100644
index 00000000..971e7a9d
--- /dev/null
+++ b/drivers/mtd/spi-nand/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_MTD_SPI_NAND) += spi-nand-base.o spi-nand-bbt.o spi-nand-device.o spi-nand-ids.o
diff --git a/drivers/mtd/spi-nand/spi-nand-base.c b/drivers/mtd/spi-nand/spi-nand-base.c
new file mode 100644
index 00000000..a2238915
--- /dev/null
+++ b/drivers/mtd/spi-nand/spi-nand-base.c
@@ -0,0 +1,2163 @@
+/**
+* spi-nand-base.c
+*
+* Copyright (c) 2009-2014 Micron Technology, Inc.
+*
+* Derived from nand_base.c
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nand.h>
+#include <linux/mtd/bbm.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include "spi-nand-ids.h"
+
+int fh_start_debug = 0;
+/*#define SPINAND_BBT_DEBUG*/
+#ifdef SPINAND_BBT_DEBUG
+#define fh_dev_debug dev_err
+#else
+#define fh_dev_debug(...)
+#endif
+
+#define ONE_WIRE_SUPPORT (1<<0)
+#define DUAL_WIRE_SUPPORT (1<<1)
+#define QUAD_WIRE_SUPPORT (1<<2)
+#define MULTI_WIRE_SUPPORT (1<<8)
+
+static int spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo);
+
+/**
+ * spi_nand_get_device - [GENERIC] Get chip for selected access
+ * @mtd: MTD device structure
+ * @new_state: the state which is requested
+ *
+ * Get the device and lock it for exclusive access
+ */
+static int spi_nand_get_device(struct mtd_info *mtd, int new_state)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ DECLARE_WAITQUEUE(wait, current);
+
+ /*
+ * Grab the lock and see if the device is available
+ */
+ while (1) {
+ spin_lock(&this->chip_lock);
+ if (this->state == FL_READY) {
+ this->state = new_state;
+ spin_unlock(&this->chip_lock);
+ break;
+ }
+ if (new_state == FL_PM_SUSPENDED) {
+ spin_unlock(&this->chip_lock);
+ return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&this->wq, &wait);
+ spin_unlock(&this->chip_lock);
+ schedule();
+ remove_wait_queue(&this->wq, &wait);
+ }
+ return 0;
+}
+
+/**
+ * spi_nand_release_device - [GENERIC] release chip
+ * @mtd: MTD device structure
+ *
+ * Deselect, release chip lock and wake up anyone waiting on the device
+ */
+static void spi_nand_release_device(struct mtd_info *mtd)
+{
+ struct spi_nand_chip *this = mtd->priv;
+
+ /* Release the chip */
+ spin_lock(&this->chip_lock);
+ this->state = FL_READY;
+ wake_up(&this->wq);
+ spin_unlock(&this->chip_lock);
+}
+
+/**
+ * __spi_nand_do_read_page - [INTERN] read data from flash to buffer
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @column :column address
+ * @raw: without ecc or not
+ * @corrected: how many bit error corrected
+ *
+ * read a page to buffer pointed by chip->buf
+ */
+static int __spi_nand_do_read_page(struct mtd_info *mtd, u32 page_addr,
+ u32 colunm, bool raw, int *corrected)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ int ret, ecc_error;
+ u8 status;
+
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+
+ /*read data from chip*/
+ memset(chip->buf, 0, chip->page_size + chip->page_spare_size);
+ if (raw) {
+ ret = chip->disable_ecc(chip);
+ if (ret < 0) {
+ pr_debug("disable ecc failed\n");
+ return ret;
+ }
+ }
+ ret = chip->load_page(chip, page_addr);
+ if (ret < 0) {
+ pr_debug("error %d loading page 0x%x to cache\n",
+ ret, page_addr);
+ return ret;
+ }
+ ret = chip->waitfunc(chip, &status);
+ if (ret < 0) {
+ pr_debug("error %d waiting page 0x%x to cache\n",
+ ret, page_addr);
+ return ret;
+ }
+ chip->get_ecc_status(chip, status, corrected, &ecc_error);
+ /*
+ * If there's an ECC error, print a message and notify MTD
+ * about it. Then complete the read, to load actual data on
+ * the buffer (instead of the status result).
+ */
+ if (ecc_error) {
+ pr_warn("internal ECC error reading page 0x%x with status 0x%02x\n",
+ page_addr, status);
+ mtd->ecc_stats.failed++;
+ } else if (*corrected)
+ mtd->ecc_stats.corrected += *corrected;
+ /* Get page from the device cache into our internal buffer */
+ ret = chip->read_cache(chip, page_addr, colunm,
+ chip->page_size + chip->page_spare_size - colunm,
+ chip->buf + colunm);
+ if (ret < 0) {
+ pr_debug("error %d reading page 0x%x from cache\n",
+ ret, page_addr);
+ return ret;
+ }
+ if (raw) {
+ ret = chip->enable_ecc(chip);
+ if (ret < 0) {
+ pr_debug("enable ecc failed\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * spi_nand_do_read_page - [INTERN] read a page from flash to buffer
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @raw: without ecc or not
+ * @corrected: how many bit error corrected
+ *
+ * read a page to buffer pointed by chip->buf
+ */
+static int spi_nand_do_read_page(struct mtd_info *mtd, u32 page_addr,
+ bool raw, int *corrected)
+{
+ return __spi_nand_do_read_page(mtd, page_addr, 0, raw, corrected);
+}
+
+/**
+ * spi_nand_do_read_page_oob - [INTERN] read page oob from flash to buffer
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @raw: without ecc or not
+ * @corrected: how many bit error corrected
+ *
+ * read page oob to buffer pointed by chip->oobbuf
+ */
+static int spi_nand_do_read_page_oob(struct mtd_info *mtd, u32 page_addr,
+ bool raw, int *corrected)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+
+ return __spi_nand_do_read_page(mtd, page_addr, chip->page_size,
+ raw, corrected);
+}
+
+
+/**
+ * __spi_nand_do_write_page - [INTERN] write data from buffer to flash
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @column :column address
+ * @raw: without ecc or not
+ *
+ * write data from buffer pointed by chip->buf to flash
+ */
+static int __spi_nand_do_write_page(struct mtd_info *mtd, u32 page_addr,
+ u32 column, bool raw)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ u8 status;
+ bool p_fail = false;
+ bool p_timeout = false;
+ int ret = 0;
+
+ fh_dev_debug(&chip->spi->dev, "Enter %s, with buf \n", __func__);
+
+ if (raw) {
+ ret = chip->disable_ecc(chip);
+ if (ret < 0) {
+ pr_debug("disable ecc failed\n");
+ return ret;
+ }
+ }
+ ret = chip->write_enable(chip);
+ if (ret < 0) {
+ pr_debug("write enable command failed\n");
+ return ret;
+ }
+ /* Store the page to cache */
+ ret = chip->store_cache(chip, page_addr, column,
+ chip->page_size + chip->page_spare_size - column,
+ chip->buf + column);
+ if (ret < 0) {
+ pr_debug("error %d storing page 0x%x to cache\n",
+ ret, page_addr);
+ return ret;
+ }
+ /* Get page from the device cache into our internal buffer */
+ ret = chip->write_page(chip, page_addr);
+ if (ret < 0) {
+ pr_debug("error %d reading page 0x%x from cache\n",
+ ret, page_addr);
+ return ret;
+ }
+ ret = chip->waitfunc(chip, &status);
+ if (ret < 0) {
+ pr_info("error %d write page 0x%x timeout\n",
+ ret, page_addr);
+ return ret;
+ }
+ if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) {
+ pr_debug("program page 0x%x failed\n", page_addr);
+ p_fail = true;
+ }
+
+ if ((status & STATUS_OIP_MASK) == STATUS_BUSY) {
+ pr_debug("program page 0x%x timeout\n", page_addr);
+ p_timeout = true;
+ }
+ if (raw) {
+ ret = chip->enable_ecc(chip);
+ if (ret < 0) {
+ pr_debug("enable ecc failed\n");
+ return ret;
+ }
+ }
+ if ((p_fail == true)||(p_timeout == true))
+ ret = -EIO;
+
+ return ret;
+}
+
+/**
+ * spi_nand_do_write_page - [INTERN] write page from buffer to flash
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @raw: without ecc or not
+ *
+ * write page from buffer pointed by chip->buf to flash
+ */
+static int spi_nand_do_write_page(struct mtd_info *mtd, u32 page_addr,
+ bool raw)
+{
+ return __spi_nand_do_write_page(mtd, page_addr, 0, raw);
+}
+
+/**
+ * spi_nand_do_write_page_oob - [INTERN] write oob from buffer to flash
+ * @mtd: MTD device structure
+ * @page_addr: page address/raw address
+ * @raw: without ecc or not
+ *
+ * write oob from buffer pointed by chip->oobbuf to flash
+ */
+static int spi_nand_do_write_page_oob(struct mtd_info *mtd, u32 page_addr,
+ bool raw)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+
+ return __spi_nand_do_write_page(mtd, page_addr, chip->page_size, raw);
+}
+
+
+/**
+ * spi_nand_transfer_oob - [INTERN] Transfer oob to client buffer
+ * @chip: SPI-NAND device structure
+ * @oob: oob destination address
+ * @ops: oob ops structure
+ * @len: size of oob to transfer
+ */
+static void spi_nand_transfer_oob(struct spi_nand_chip *chip, u8 *oob,
+ struct mtd_oob_ops *ops, size_t len)
+{
+ switch (ops->mode) {
+
+ case MTD_OOB_PLACE: /*MTD_OPS_PLACE_OOB:*/
+ case MTD_OOB_RAW: /*MTD_OPS_RAW:*/
+ memcpy(oob, chip->oobbuf + ops->ooboffs, len);
+ return;
+
+ case MTD_OOB_AUTO: { /*MTD_OPS_AUTO_OOB:*/
+ struct nand_oobfree *free = chip->ecclayout->oobfree;
+ uint32_t boffs = 0, roffs = ops->ooboffs;
+ size_t bytes = 0;
+
+ for (; free->length && len; free++, len -= bytes) {
+ /* Read request not from offset 0? */
+ if (unlikely(roffs)) {
+ if (roffs >= free->length) {
+ roffs -= free->length;
+ continue;
+ }
+ boffs = free->offset + roffs;
+ bytes = min_t(size_t, len,
+ (free->length - roffs));
+ roffs = 0;
+ } else {
+ bytes = min_t(size_t, len, free->length);
+ boffs = free->offset;
+ }
+ memcpy(oob, chip->oobbuf + boffs, bytes);
+ oob += bytes;
+ }
+ return;
+ }
+ default:
+ BUG();
+ }
+}
+
+/**
+ * spi_nand_fill_oob - [INTERN] Transfer client buffer to oob
+ * @chip: SPI-NAND device structure
+ * @oob: oob data buffer
+ * @len: oob data write length
+ * @ops: oob ops structure
+ */
+static void spi_nand_fill_oob(struct spi_nand_chip *chip, uint8_t *oob,
+ size_t len, struct mtd_oob_ops *ops)
+{
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+ memset(chip->oobbuf, 0xff, chip->page_spare_size);
+
+ switch (ops->mode) {
+
+ case MTD_OOB_PLACE:
+ case MTD_OOB_RAW:
+ memcpy(chip->oobbuf + ops->ooboffs, oob, len);
+ return;
+
+ case MTD_OOB_AUTO: {
+ struct nand_oobfree *free = chip->ecclayout->oobfree;
+ uint32_t boffs = 0, woffs = ops->ooboffs;
+ size_t bytes = 0;
+
+ for (; free->length && len; free++, len -= bytes) {
+ /* Write request not from offset 0? */
+ if (unlikely(woffs)) {
+ if (woffs >= free->length) {
+ woffs -= free->length;
+ continue;
+ }
+ boffs = free->offset + woffs;
+ bytes = min_t(size_t, len,
+ (free->length - woffs));
+ woffs = 0;
+ } else {
+ bytes = min_t(size_t, len, free->length);
+ boffs = free->offset;
+ }
+ memcpy(chip->oobbuf + boffs, oob, bytes);
+ oob += bytes;
+ }
+ return;
+ }
+ default:
+ BUG();
+ }
+}
+
+/**
+ * spi_nand_do_read_ops - [INTERN] Read data with ECC
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob ops structure
+ *
+ * Internal function. Called with chip held.
+ */
+static int spi_nand_do_read_ops(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ int page_addr, page_offset, size;
+ int ret;
+ unsigned int corrected = 0;
+ struct mtd_ecc_stats stats;
+ unsigned int max_bitflips = 0;
+ int readlen = ops->len;
+ int oobreadlen = ops->ooblen;
+ int ooblen = ops->mode == MTD_OOB_AUTO ?
+ mtd->oobavail : mtd->oobsize;
+
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+
+ /* Do not allow reads past end of device */
+ if (unlikely(from >= mtd->size)) {
+ pr_debug("%s: attempt to read beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+ stats = mtd->ecc_stats;
+
+ page_addr = from >> chip->page_shift;
+
+ /* for main data */
+ page_offset = from & chip->page_mask;
+ ops->retlen = 0;
+
+ /* for oob */
+ if (oobreadlen > 0) {
+ if (unlikely(ops->ooboffs >= ooblen)) {
+ pr_debug("%s: attempt to start read outside oob\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (unlikely(ops->ooboffs + oobreadlen >
+ ((mtd->size >> chip->page_shift) - (from >> chip->page_shift))
+ * ooblen)) {
+ pr_debug("%s: attempt to read beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+ ooblen -= ops->ooboffs;
+ ops->oobretlen = 0;
+ }
+
+ while (1) {
+ if (page_addr != chip->pagebuf || oobreadlen > 0) {
+ ret = spi_nand_do_read_page(mtd, page_addr,
+ ops->mode == MTD_OOB_RAW, &corrected);
+ if (ret) {
+ pr_debug("error %d reading page 0x%x\n",
+ ret, page_addr);
+ return ret;
+ }
+ chip->pagebuf_bitflips = corrected;
+ chip->pagebuf = page_addr;
+ }
+ max_bitflips = max(max_bitflips, chip->pagebuf_bitflips);
+ size = min(readlen, chip->page_size - page_offset);
+ memcpy(ops->datbuf + ops->retlen,
+ chip->buf + page_offset, size);
+
+ ops->retlen += size;
+ readlen -= size;
+ page_offset = 0;
+
+ if (unlikely(ops->oobbuf)) {
+ size = min(oobreadlen, ooblen);
+ spi_nand_transfer_oob(chip,
+ ops->oobbuf + ops->oobretlen, ops, size);
+
+ ops->oobretlen += size;
+ oobreadlen -= size;
+ }
+ if (!readlen)
+ break;
+
+ page_addr++;
+ }
+
+ if (mtd->ecc_stats.failed - stats.failed)
+ return -EBADMSG;
+
+ return max_bitflips;
+}
+
+/**
+ * spi_nand_do_write_ops - [INTERN] SPI-NAND write with ECC
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operations description structure
+ *
+ */
+static int spi_nand_do_write_ops(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ int page_addr, page_offset, size;
+ int writelen = ops->len;
+ int oobwritelen = ops->ooblen;
+ int ret;
+ int ooblen = ops->mode == MTD_OOB_AUTO ?
+ mtd->oobavail : mtd->oobsize;
+
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+
+ /* Do not allow reads past end of device */
+ if (unlikely(to >= mtd->size)) {
+ pr_debug("%s: attempt to write beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ page_addr = to >> chip->page_shift;
+
+ /* for main data */
+ page_offset = to & chip->page_mask;
+ ops->retlen = 0;
+
+ /* for oob */
+ if (oobwritelen > 0) {
+ /* Do not allow write past end of page */
+ if ((ops->ooboffs + oobwritelen) > ooblen) {
+ pr_debug("%s: attempt to write past end of page\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (unlikely(ops->ooboffs >= ooblen)) {
+ pr_debug("%s: attempt to start write outside oob\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (unlikely(ops->ooboffs + oobwritelen >
+ ((mtd->size >> chip->page_shift) - (to >> chip->page_shift))
+ * ooblen)) {
+ pr_debug("%s: attempt to write beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+ ooblen -= ops->ooboffs;
+ ops->oobretlen = 0;
+ }
+
+ chip->pagebuf = -1;
+
+ while (1) {
+ memset(chip->buf, 0xFF,
+ chip->page_size + chip->page_spare_size);
+
+ size = min(writelen, chip->page_size - page_offset);
+ memcpy(chip->buf + page_offset,
+ ops->datbuf + ops->retlen, size);
+
+ ops->retlen += size;
+ writelen -= size;
+ page_offset = 0;
+
+ if (unlikely(ops->oobbuf)) {
+ size = min(oobwritelen, ooblen);
+
+ spi_nand_fill_oob(chip, ops->oobbuf + ops->oobretlen,
+ size, ops);
+
+ ops->oobretlen += size;
+ oobwritelen -= size;
+ }
+ ret = spi_nand_do_write_page(mtd, page_addr,
+ ops->mode == MTD_OOB_RAW);
+ if (ret) {
+ pr_debug("error %d writing page 0x%x\n",
+ ret, page_addr);
+ return ret;
+ }
+ if (!writelen)
+ break;
+ page_addr++;
+ }
+ return 0;
+}
+
+/**
+ * nand_read - [MTD Interface] SPI-NAND read
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @len: number of bytes to read
+ * @retlen: pointer to variable to store the number of read bytes
+ * @buf: the databuffer to put data
+ *
+ */
+static int spi_nand_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct mtd_oob_ops ops = { 0 };
+ int ret;
+
+ spi_nand_get_device(mtd, FL_READING);
+
+ ops.len = len;
+ ops.datbuf = buf;
+ ret = spi_nand_do_read_ops(mtd, from, &ops);
+
+ *retlen = ops.retlen;
+
+ spi_nand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * spi_nand_write - [MTD Interface] SPI-NAND write
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @len: number of bytes to write
+ * @retlen: pointer to variable to store the number of written bytes
+ * @buf: the data to write
+ *
+ */
+static int spi_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct mtd_oob_ops ops = {0};
+ int ret;
+
+ spi_nand_get_device(mtd, FL_WRITING);
+
+ ops.len = len;
+ ops.datbuf = (uint8_t *)buf;
+
+
+ ret = spi_nand_do_write_ops(mtd, to, &ops);
+
+ *retlen = ops.retlen;
+
+ spi_nand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * spi_nand_do_read_oob - [INTERN] SPI-NAND read out-of-band
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operations description structure
+ *
+ * SPI-NAND read out-of-band data from the spare area.
+ */
+static int spi_nand_do_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ int page_addr;
+ int corrected = 0;
+ struct mtd_ecc_stats stats;
+ int readlen = ops->ooblen;
+ int len;
+ int ret = 0;
+
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+
+ pr_debug("%s: from = 0x%08Lx, len = %i\n",
+ __func__, (unsigned long long)from, readlen);
+
+ stats = mtd->ecc_stats;
+
+ len = ops->mode == MTD_OOB_AUTO ? mtd->oobavail : mtd->oobsize;
+
+ if (unlikely(ops->ooboffs >= len)) {
+ pr_debug("%s: attempt to start read outside oob\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Do not allow reads past end of device */
+ if (unlikely(from >= mtd->size ||
+ ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
+ (from >> chip->page_shift)) * len)) {
+ pr_debug("%s: attempt to read beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Shift to get page */
+ page_addr = (from >> chip->page_shift);
+ len -= ops->ooboffs;
+ ops->oobretlen = 0;
+
+ while (1) {
+ /*read data from chip*/
+ ret = spi_nand_do_read_page_oob(mtd, page_addr,
+ ops->mode == MTD_OOB_RAW, &corrected);
+ if (ret) {
+ pr_debug("error %d reading page 0x%x\n",
+ ret, page_addr);
+ return ret;
+ }
+ if (page_addr == chip->pagebuf)
+ chip->pagebuf = -1;
+
+ len = min(len, readlen);
+ spi_nand_transfer_oob(chip, ops->oobbuf + ops->oobretlen,
+ ops, len);
+
+ readlen -= len;
+ ops->oobretlen += len;
+ if (!readlen)
+ break;
+
+ page_addr++;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ if (mtd->ecc_stats.failed - stats.failed)
+ return -EBADMSG;
+
+ return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+}
+
+/**
+ * spi_nand_do_write_oob - [MTD Interface] SPI-NAND write out-of-band
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
+ *
+ * SPI-NAND write out-of-band.
+ */
+static int spi_nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ int page_addr, len, ret;
+ struct spi_nand_chip *chip = mtd->priv;
+ int writelen = ops->ooblen;
+
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+
+ pr_debug("%s: to = 0x%08x, len = %i\n",
+ __func__, (unsigned int)to, (int)writelen);
+
+ len = ops->mode == MTD_OOB_AUTO ? mtd->oobavail : mtd->oobsize;
+
+ /* Do not allow write past end of page */
+ if ((ops->ooboffs + writelen) > len) {
+ pr_debug("%s: attempt to write past end of page\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (unlikely(ops->ooboffs >= len)) {
+ pr_debug("%s: attempt to start write outside oob\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Do not allow write past end of device */
+ if (unlikely(to >= mtd->size ||
+ ops->ooboffs + writelen >
+ ((mtd->size >> chip->page_shift) -
+ (to >> chip->page_shift)) * len)) {
+ pr_debug("%s: attempt to write beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Shift to get page */
+ page_addr = to >> chip->page_shift;
+ /* Invalidate the page cache, if we write to the cached page */
+ if (page_addr == chip->pagebuf)
+ chip->pagebuf = -1;
+
+ spi_nand_fill_oob(chip, ops->oobbuf, writelen, ops);
+
+ ret = spi_nand_do_write_page_oob(mtd, page_addr,
+ ops->mode == MTD_OOB_RAW);
+ if (ret) {
+ pr_debug("error %d writing page 0x%x\n",
+ ret, page_addr);
+ return ret;
+ }
+ ops->oobretlen = writelen;
+
+ return 0;
+}
+
+/**
+ * spi_nand_read_oob - [MTD Interface] SPI-NAND read data and/or out-of-band
+ * @mtd: MTD device structure
+ * @from: offset to read from
+ * @ops: oob operation description structure
+ *
+ * SPI-NAND read data and/or out-of-band data.
+ */
+static int spi_nand_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ int ret = -ENOTSUPP;
+#ifdef SPINAND_BBT_DEBUG
+ struct spi_nand_chip *this = mtd->priv;
+ fh_dev_debug(&this->spi->dev, "Enter %s, from 0x%08llx \n", __func__, from);
+#endif
+ ops->retlen = 0;
+
+ /* Do not allow reads past end of device */
+ if (ops->datbuf && (from + ops->len) > mtd->size) {
+ pr_debug("%s: attempt to read beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ spi_nand_get_device(mtd, FL_READING);
+
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ case MTD_OOB_RAW:
+ break;
+
+ default:
+ goto out;
+ }
+
+ if (!ops->datbuf)
+ ret = spi_nand_do_read_oob(mtd, from, ops);
+ else
+ ret = spi_nand_do_read_ops(mtd, from, ops);
+
+out:
+ spi_nand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * spi_nand_write_oob - [MTD Interface] SPI-NAND write data and/or out-of-band
+ * @mtd: MTD device structure
+ * @to: offset to write to
+ * @ops: oob operation description structure
+ */
+static int spi_nand_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ int ret = -ENOTSUPP;
+#ifdef SPINAND_BBT_DEBUG
+ struct spi_nand_chip *this = mtd->priv;
+ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__);
+#endif
+ ops->retlen = 0;
+
+ /* Do not allow writes past end of device */
+ if (ops->datbuf && (to + ops->len) > mtd->size) {
+ pr_debug("%s: attempt to write beyond end of device\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ spi_nand_get_device(mtd, FL_WRITING);
+
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ case MTD_OOB_RAW:
+ break;
+
+ default:
+ goto out;
+ }
+
+ if (!ops->datbuf)
+ ret = spi_nand_do_write_oob(mtd, to, ops);
+ else
+ ret = spi_nand_do_write_ops(mtd, to, ops);
+
+out:
+ spi_nand_release_device(mtd);
+
+ return ret;
+}
+
+/**
+ * spi_nand_block_bad - [INTERN] Check if block at offset is bad
+ * @mtd: MTD device structure
+ * @offs: offset relative to mtd start
+ */
+static int spi_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ struct mtd_oob_ops ops = {0};
+ u32 block_addr;
+ u8 bad[2] = {0, 0};
+ u8 ret = 0;
+
+ block_addr = ofs >> chip->block_shift;
+ ops.mode = MTD_OOB_PLACE;
+ ops.ooblen = 2;
+ ops.oobbuf = bad;
+
+ ret = spi_nand_do_read_oob(mtd, block_addr << chip->block_shift, &ops);
+ if (bad[0] != 0xFF || bad[1] != 0xFF)
+ ret = 1;
+
+ return ret;
+
+}
+
+/**
+ * spi_nand_block_checkbad - [GENERIC] Check if a block is marked bad
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ * @allowbbt: 1, if its allowed to access the bbt area
+ *
+ * Check, if the block is bad. Either by reading the bad block table or
+ * calling of the scan function.
+ */
+static int spi_nand_block_checkbad(struct mtd_info *mtd, loff_t ofs,
+ int allowbbt)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+
+ if (!chip->bbt)
+ return spi_nand_block_bad(mtd, ofs);
+
+ /* Return info from the table */
+ return spi_nand_isbad_bbt(mtd, ofs, allowbbt);
+}
+
+/**
+ * spi_nand_block_isbad - [MTD Interface] Check if block at offset is bad
+ * @mtd: MTD device structure
+ * @offs: offset relative to mtd start
+ */
+static int spi_nand_block_isbad(struct mtd_info *mtd, loff_t offs)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ return chip->block_bad(mtd, offs, 0);
+}
+
+/**
+ * spi_nand_block_markbad_lowlevel - mark a block bad
+ * @mtd: MTD device structure
+ * @ofs: offset from device start
+ *
+ * This function performs the generic bad block marking steps (i.e., bad
+ * block table(s) and/or marker(s)). We only allow the hardware driver to
+ * specify how to write bad block markers to OOB (chip->block_markbad).
+ *
+ * We try operations in the following order:
+ * (1) erase the affected block, to allow OOB marker to be written cleanly
+ * (2) write bad block marker to OOB area of affected block (unless flag
+ * NAND_BBT_NO_OOB_BBM is present)
+ * (3) update the BBT
+ * Note that we retain the first error encountered in (2) or (3), finish the
+ * procedures, and dump the error in the end.
+*/
+static int spi_nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ struct mtd_oob_ops ops = {0};
+ struct erase_info einfo = {0};
+ u32 block_addr;
+ u8 buf[2] = {0, 0};
+ int res, ret = 0;
+
+ if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
+ /*erase bad block before mark bad block*/
+ einfo.mtd = mtd;
+ einfo.addr = ofs;
+ einfo.len = 1UL << chip->block_shift;
+ spi_nand_erase(mtd, &einfo);
+
+ block_addr = ofs >> chip->block_shift;
+ ops.mode = MTD_OOB_PLACE;
+ ops.ooblen = 2;
+ ops.oobbuf = buf;
+
+ ret = spi_nand_do_write_oob(mtd,
+ block_addr << chip->block_shift, &ops);
+ }
+
+ /* Mark block bad in BBT */
+ if (chip->bbt) {
+ res = spi_nand_markbad_bbt(mtd, ofs);
+ if (!ret)
+ ret = res;
+ }
+
+ if (!ret)
+ mtd->ecc_stats.badblocks++;
+
+ return ret;
+}
+
+/**
+ * spi_nand_block_markbad - [MTD Interface] Mark block at the given offset
+ * as bad
+ * @mtd: MTD device structure
+ * @ofs: offset relative to mtd start
+ */
+static int spi_nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ int ret;
+
+ ret = spi_nand_block_isbad(mtd, ofs);
+ if (ret) {
+ /* If it was bad already, return success and do nothing */
+ if (ret > 0)
+ return 0;
+ return ret;
+ }
+
+ return spi_nand_block_markbad_lowlevel(mtd, ofs);
+}
+
+/**
+ * __spi_nand_erase - [INTERN] erase block(s)
+ * @mtd: MTD device structure
+ * @einfo: erase instruction
+ * @allowbbt: allow to access bbt
+ *
+ * Erase one ore more blocks
+ */
+int __spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo,
+ int allowbbt)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ int page_addr, pages_per_block;
+ loff_t len;
+ u8 status;
+ int ret = 0;
+
+
+ /* check address align on block boundary */
+ if (einfo->addr & (chip->block_size - 1)) {
+ pr_debug("%s: Unaligned address\n", __func__);
+ return -EINVAL;
+ }
+
+ if (einfo->len & (chip->block_size - 1)) {
+ pr_debug("%s: Length not block aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Do not allow erase past end of device */
+ if ((einfo->len + einfo->addr) > chip->size) {
+ pr_debug("%s: Erase past end of device\n", __func__);
+ return -EINVAL;
+ }
+
+ einfo->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+
+ /* Grab the lock and see if the device is available */
+ spi_nand_get_device(mtd, FL_ERASING);
+
+ pages_per_block = 1 << (chip->block_shift - chip->page_shift);
+ page_addr = einfo->addr >> chip->page_shift;
+ len = einfo->len;
+
+ einfo->state = MTD_ERASING;
+
+ while (len) {
+ /* Check if we have a bad block, we do not erase bad blocks! */
+ if (chip->block_bad(mtd, ((loff_t) page_addr) <<
+ chip->page_shift, allowbbt)) {
+ pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
+ __func__, page_addr);
+ einfo->state = MTD_ERASE_FAILED;
+ goto erase_exit;
+ }
+ /*
+ * Invalidate the page cache, if we erase the block which
+ * contains the current cached page.
+ */
+ if (page_addr <= chip->pagebuf && chip->pagebuf <
+ (page_addr + pages_per_block))
+ chip->pagebuf = -1;
+
+ ret = chip->write_enable(chip);
+ if (ret < 0) {
+ pr_debug("write enable command failed\n");
+ einfo->state = MTD_ERASE_FAILED;
+ goto erase_exit;
+ }
+
+ ret = chip->erase_block(chip, page_addr);
+ if (ret < 0) {
+ pr_debug("block erase command failed\n");
+ einfo->state = MTD_ERASE_FAILED;
+ einfo->fail_addr = (loff_t)page_addr
+ << chip->page_shift;
+ goto erase_exit;
+ }
+ ret = chip->waitfunc(chip, &status);
+ if (ret < 0) {
+ pr_debug("block erase command wait failed\n");
+ einfo->state = MTD_ERASE_FAILED;
+ goto erase_exit;
+ }
+ if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) {
+ pr_debug("erase block 0x%012llx failed\n",
+ ((loff_t) page_addr) << chip->page_shift);
+ einfo->state = MTD_ERASE_FAILED;
+ einfo->fail_addr = (loff_t)page_addr
+ << chip->page_shift;
+ goto erase_exit;
+ }
+
+ /* Increment page address and decrement length */
+ len -= (1ULL << chip->block_shift);
+ page_addr += pages_per_block;
+ }
+
+ einfo->state = MTD_ERASE_DONE;
+
+erase_exit:
+
+ ret = einfo->state == MTD_ERASE_DONE ? 0 : -EIO;
+
+ spi_nand_release_device(mtd);
+
+ /* Do call back function */
+ if (!ret)
+ mtd_erase_callback(einfo);
+
+ /* Return more or less happy */
+ return ret;
+}
+EXPORT_SYMBOL(__spi_nand_erase);
+
+/**
+ * spi_nand_erase - [MTD Interface] erase block(s)
+ * @mtd: MTD device structure
+ * @einfo: erase instruction
+ *
+ * Erase one ore more blocks
+ */
+static int spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo)
+{
+ return __spi_nand_erase(mtd, einfo, 0);
+}
+
+/**
+ * spi_nand_sync - [MTD Interface] sync
+ * @mtd: MTD device structure
+ *
+ * Sync is actually a wait for chip ready function
+ */
+static void spi_nand_sync(struct mtd_info *mtd)
+{
+ pr_debug("spi_nand_sync: called\n");
+
+ /* Grab the lock and see if the device is available */
+ spi_nand_get_device(mtd, FL_SYNCING);
+
+ /* Release it and go back */
+ spi_nand_release_device(mtd);
+}
+
+/**
+ * spi_nand_suspend - [MTD Interface] Suspend the SPI-NAND flash
+ * @mtd: MTD device structure
+ */
+static int spi_nand_suspend(struct mtd_info *mtd)
+{
+ return spi_nand_get_device(mtd, FL_PM_SUSPENDED);
+}
+
+/**
+ * spi_nand_resume - [MTD Interface] Resume the SPI-NAND flash
+ * @mtd: MTD device structure
+ */
+static void spi_nand_resume(struct mtd_info *mtd)
+{
+ struct spi_nand_chip *this = mtd->priv;
+
+ if (this->state == FL_PM_SUSPENDED)
+ spi_nand_release_device(mtd);
+ else
+ pr_err("%s is not called in suspended state\n:", __func__);
+}
+
+
+/*
+ * spi_nand_send_cmd - to process a command to send to the SPI-NAND
+ * @spi: spi device structure
+ * @cmd: command structure
+ *
+ * Set up the command buffer to send to the SPI controller.
+ * The command buffer has to initialized to 0.
+ */
+int spi_nand_send_cmd(struct spi_device *spi, struct spi_nand_cmd *cmd)
+{
+ struct spi_message message;
+ struct spi_transfer x[4];
+ u8 buf[8], i;
+ u32 buflen = 0;
+
+ spi_message_init(&message);
+ memset(x, 0, sizeof(x));
+ x[0].len = 1;
+ x[0].tx_buf = &cmd->cmd;
+ x[0].rx_nbits = 0;
+ spi_message_add_tail(&x[0], &message);
+
+ buf[buflen++] = cmd->cmd;
+
+ if (cmd->n_addr) {
+ x[1].len = cmd->n_addr;
+ x[1].tx_buf = cmd->addr;
+ spi_message_add_tail(&x[1], &message);
+ x[1].rx_nbits = 0;
+ }
+ for (i = 0; i < cmd->n_addr && buflen < 7; i++)
+ buf[buflen++] = cmd->addr[i];
+
+ if (cmd->n_tx) {
+ x[2].len = cmd->n_tx;
+ /*x[2].tx_nbits = cmd->tx_nbits; always 0 for single future version*/
+ x[2].tx_buf = cmd->tx_buf;
+ x[2].rx_nbits = 0;
+ spi_message_add_tail(&x[2], &message);
+ }
+ for (i = 0; i < cmd->n_tx && buflen < 7; i++)
+ buf[buflen++] = cmd->tx_buf[i];
+
+ if (cmd->n_rx) {
+ x[3].len = cmd->n_rx;
+ /*x[3].rx_nbits = cmd->rx_nbits;*/
+ x[3].rx_buf = cmd->rx_buf;
+ if (cmd->cmd == SPINAND_CMD_READ_CACHE_X4)
+ x[3].rx_nbits = 4;
+ else if (cmd->cmd == SPINAND_CMD_READ_CACHE_X2)
+ x[3].rx_nbits = 2;
+ else
+ x[3].rx_nbits = 0;
+ spi_message_add_tail(&x[3], &message);
+ }
+ for (i = 0; i < cmd->n_rx && buflen < 7; i++)
+ buf[buflen++] = cmd->rx_buf[i];
+
+ buflen = 1 + cmd->n_addr + cmd->n_tx + cmd->n_rx;
+ if (fh_start_debug || cmd->cmd == 0x1f)
+ fh_dev_debug(&spi->dev, " spi%d:%d: send cmd 0x: %02x %02x %02x %02x %02x %02x, size %d\n",
+ spi->master->bus_num, spi->chip_select,
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buflen);
+
+ return spi_sync(spi, &message);
+}
+EXPORT_SYMBOL(spi_nand_send_cmd);
+/*
+ * spi_nand_read_status- send command 0x0f to the SPI-NAND status register value
+ * @spi: spi device structure
+ * @status: buffer to store value
+ * Description:
+ * After read, write, or erase, the Nand device is expected to set the
+ * busy status.
+ * This function is to allow reading the status of the command: read,
+ * write, and erase.
+ * Once the status turns to be ready, the other status bits also are
+ * valid status bits.
+ */
+static int spi_nand_read_status(struct spi_device *spi, uint8_t *status)
+{
+ struct spi_nand_cmd cmd = {0};
+ int ret;
+
+ cmd.cmd = SPINAND_CMD_READ_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_STATUS;
+ cmd.n_rx = 1;
+ cmd.rx_buf = status;
+
+ ret = spi_nand_send_cmd(spi, &cmd);
+ if (ret < 0)
+ dev_err(&spi->dev, "err: %d read status register\n", ret);
+
+ return ret;
+}
+
+/**
+ * spi_nand_get_otp- send command 0x0f to read the SPI-NAND OTP register
+ * @spi: spi device structure
+ * @opt: buffer to store value
+ * Description:
+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ * Enable chip internal ECC, set the bit to 1
+ * Disable chip internal ECC, clear the bit to 0
+ */
+static int spi_nand_get_otp(struct spi_device *spi, u8 *otp)
+{
+ struct spi_nand_cmd cmd = {0};
+ int ret;
+
+ cmd.cmd = SPINAND_CMD_READ_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_OTP;
+ cmd.n_rx = 1;
+ cmd.rx_buf = otp;
+
+ ret = spi_nand_send_cmd(spi, &cmd);
+ if (ret < 0)
+ dev_err(&spi->dev, "error %d get otp\n", ret);
+ return ret;
+}
+
+/**
+ * spi_nand_set_otp- send command 0x1f to write the SPI-NAND OTP register
+ * @spi: spi device structure
+ * @status: buffer stored value
+ * Description:
+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ * Enable chip internal ECC, set the bit to 1
+ * Disable chip internal ECC, clear the bit to 0
+ */
+static int spi_nand_set_otp(struct spi_device *spi, u8 *otp)
+{
+ int ret;
+ struct spi_nand_cmd cmd = { 0 };
+
+ cmd.cmd = SPINAND_CMD_WRITE_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_OTP;
+ cmd.n_tx = 1;
+ cmd.tx_buf = otp;
+
+ ret = spi_nand_send_cmd(spi, &cmd);
+ if (ret < 0)
+ dev_err(&spi->dev, "error %d set otp\n", ret);
+
+ return ret;
+}
+
+/**
+ * spi_nand_enable_ecc- enable internal ECC
+ * @chip: SPI-NAND device structure
+ * Description:
+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ * Enable chip internal ECC, set the bit to 1
+ * Disable chip internal ECC, clear the bit to 0
+ */
+static int spi_nand_enable_ecc(struct spi_nand_chip *chip)
+{
+ struct spi_device *spi = chip->spi;
+ int ret;
+ u8 otp = 0;
+
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ ret = spi_nand_get_otp(spi, &otp);
+ if (ret < 0)
+ return ret;
+
+ fh_dev_debug(&spi->dev, "get opt: 0x%02x\n", otp);
+ if ((otp & OTP_ECC_MASK) == OTP_ECC_ENABLE)
+ return 0;
+
+ otp |= OTP_ECC_ENABLE;
+ ret = spi_nand_set_otp(spi, &otp);
+ if (ret < 0)
+ return ret;
+ fh_dev_debug(&spi->dev, "set opt: 0x%02x\n", otp);
+ return spi_nand_get_otp(spi, &otp);
+}
+
+static int spi_nand_get_qe_value(struct spi_nand_chip *chip, u8 *otp)
+{
+ struct spi_nand_cmd cmd = {0};
+ int ret;
+
+ cmd.cmd = SPINAND_CMD_READ_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = chip->qe_addr;
+ cmd.n_rx = 1;
+ cmd.rx_buf = otp;
+
+ ret = spi_nand_send_cmd(chip->spi, &cmd);
+ return ret;
+}
+
+static int spi_nand_set_qe_value(struct spi_nand_chip *chip, u8 *otp)
+{
+ int ret;
+ struct spi_nand_cmd cmd = { 0 };
+
+ cmd.cmd = SPINAND_CMD_WRITE_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = chip->qe_addr;
+ cmd.n_tx = 1;
+ cmd.tx_buf = otp;
+
+ ret = spi_nand_send_cmd(chip->spi, &cmd);
+ return ret;
+}
+
+
+
+static int spi_nand_set_qe(struct spi_nand_chip *chip)
+{
+ int ret;
+ u8 otp = 0;
+
+ if (!chip->qe_addr)
+ return 0;
+
+ ret = spi_nand_get_qe_value(chip, &otp);
+ if (ret < 0)
+ return ret;
+
+ if (chip->qe_flag)
+ otp |= chip->qe_mask;
+ else
+ otp &= (~chip->qe_mask);
+ ret = spi_nand_set_qe_value(chip, &otp);
+ if (ret < 0)
+ return ret;
+ return spi_nand_get_qe_value(chip, &otp);
+}
+
+
+/**
+ * spi_nand_disable_ecc- disable internal ECC
+ * @chip: SPI-NAND device structure
+ * Description:
+ * There is one bit( bit 0x10 ) to set or to clear the internal ECC.
+ * Enable chip internal ECC, set the bit to 1
+ * Disable chip internal ECC, clear the bit to 0
+ */
+static int spi_nand_disable_ecc(struct spi_nand_chip *chip)
+{
+ struct spi_device *spi = chip->spi;
+ int ret;
+ u8 otp = 0;
+
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+ ret = spi_nand_get_otp(spi, &otp);
+ if (ret < 0)
+ return ret;
+
+ if ((otp & OTP_ECC_MASK) == OTP_ECC_ENABLE) {
+ otp &= ~OTP_ECC_ENABLE;
+ ret = spi_nand_set_otp(spi, &otp);
+ if (ret < 0)
+ return ret;
+ return spi_nand_get_otp(spi, &otp);
+ } else
+ return 0;
+}
+
+/**
+ * spi_nand_write_enable- send command 0x06 to enable write or erase the
+ * Nand cells
+ * @chip: SPI-NAND device structure
+ * Description:
+ * Before write and erase the Nand cells, the write enable has to be set.
+ * After the write or erase, the write enable bit is automatically
+ * cleared (status register bit 2)
+ * Set the bit 2 of the status register has the same effect
+ */
+static int spi_nand_write_enable(struct spi_nand_chip *chip)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ cmd.cmd = SPINAND_CMD_WR_ENABLE;
+ return spi_nand_send_cmd(spi, &cmd);
+}
+
+/*
+ * spi_nand_read_from_cache- send command 0x13 to read data from Nand to cache
+ * @chip: SPI-NAND device structure
+ * @page_addr: page to read
+ */
+static int spi_nand_read_page_to_cache(struct spi_nand_chip *chip,
+ u32 page_addr)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ cmd.cmd = SPINAND_CMD_READ;
+ cmd.n_addr = 3;
+ cmd.addr[0] = (u8)(page_addr >> 16);
+ cmd.addr[1] = (u8)(page_addr >> 8);
+ cmd.addr[2] = (u8)page_addr;
+
+ return spi_nand_send_cmd(spi, &cmd);
+}
+
+/*
+ * spi_nand_read_from_cache- send command 0x03 to read out the data from the
+ * cache register
+ * Description:
+ * The read can specify 1 to (page size + spare size) bytes of data read at
+ * the corresponding locations.
+ * No tRd delay.
+ */
+int spi_nand_read_from_cache(struct spi_nand_chip *chip, u32 page_addr,
+ u32 column, size_t len, u8 *rbuf)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ /*cmd.cmd = SPINAND_CMD_READ_RDM;*/
+ cmd.n_addr = 3;
+ if (spi->mode & SPI_RX_QUAD) {
+ cmd.cmd = SPINAND_CMD_READ_CACHE_X4;
+ if (chip->multi_wire_command_length == 5)
+ cmd.n_addr = 4;
+ } else if (spi->mode & SPI_RX_DUAL) {
+ cmd.cmd = SPINAND_CMD_READ_CACHE_X2;
+ if (chip->multi_wire_command_length == 5)
+ cmd.n_addr = 4;
+ } else
+ cmd.cmd = SPINAND_CMD_READ_RDM;
+ /*FIXME: early GD chips, test 1G*/
+ if (chip->options & FIRST_DUMMY_BYTE) {
+ cmd.addr[0] = 0;
+ cmd.addr[1] = (u8)(column >> 8);
+ if (chip->options & SPINAND_NEED_PLANE_SELECT)
+ cmd.addr[0] |= (u8)(((page_addr >>
+ (chip->block_shift - chip->page_shift)) & 0x1) << 4);
+ cmd.addr[2] = (u8)column;
+ }
+ else{
+ cmd.addr[0] = (u8)(column >> 8);
+ if (chip->options & SPINAND_NEED_PLANE_SELECT)
+ cmd.addr[0] |= (u8)(((page_addr >>
+ (chip->block_shift - chip->page_shift)) & 0x1) << 4);
+ cmd.addr[1] = (u8)column;
+ cmd.addr[2] = 0;
+ }
+ cmd.n_rx = len;
+ cmd.rx_buf = rbuf;
+
+ return spi_nand_send_cmd(spi, &cmd);
+}
+
+/*
+ * spi_nand_read_from_cache_x2- send command 0x3b to read out the data from the
+ * cache register
+ * Description:
+ * The read can specify 1 to (page size + spare size) bytes of data read at
+ * the corresponding locations.
+ * No tRd delay.
+ */
+/*int spi_nand_read_from_cache_x2(struct spi_nand_chip *chip, u32 page_addr,
+ u32 column, size_t len, u8 *rbuf)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+
+ cmd.cmd = SPINAND_CMD_READ_CACHE_X2;
+ cmd.n_addr = 3;
+ cmd.addr[0] = (u8)(column >> 8);
+ if (chip->options & SPINAND_NEED_PLANE_SELECT)
+ cmd.addr[0] |= (u8)(((page_addr >>
+ (chip->block_shift - chip->page_shift)) & 0x1) << 4);
+ cmd.addr[1] = (u8)column;
+ cmd.addr[2] = 0;
+ cmd.n_rx = len;
+ cmd.rx_nbits = SPI_NBITS_DUAL;
+ cmd.rx_buf = rbuf;
+
+ return spi_nand_send_cmd(spi, &cmd);
+}*/
+
+/*
+ * spi_nand_read_from_cache_x4- send command 0x6b to read out the data from the
+ * cache register
+ * Description:
+ * The read can specify 1 to (page size + spare size) bytes of data read at
+ * the corresponding locations.
+ * No tRd delay.
+ */
+/*int spi_nand_read_from_cache_x4(struct spi_nand_chip *chip, u32 page_addr,
+ u32 column, size_t len, u8 *rbuf)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+
+ cmd.cmd = SPINAND_CMD_READ_CACHE_X4;
+ cmd.n_addr = 3;
+ cmd.addr[0] = (u8)(column >> 8);
+ if (chip->options & SPINAND_NEED_PLANE_SELECT)
+ cmd.addr[0] |= (u8)(((page_addr >>
+ (chip->block_shift - chip->page_shift)) & 0x1) << 4);
+ cmd.addr[1] = (u8)column;
+ cmd.addr[2] = 0;
+ cmd.n_rx = len;
+ cmd.rx_nbits = SPI_NBITS_QUAD;
+ cmd.rx_buf = rbuf;
+
+ return spi_nand_send_cmd(spi, &cmd);
+}*/
+
+/*
+ * spi_nand_read_from_cache_snor_protocol- send command 0x03 to read out the
+ * data from the cache register, 0x03 command protocol is same as SPI NOR
+ * read command
+ * Description:
+ * The read can specify 1 to (page size + spare size) bytes of data read at
+ * the corresponding locations.
+ * No tRd delay.
+ */
+int spi_nand_read_from_cache_snor_protocol(struct spi_nand_chip *chip,
+ u32 page_addr, u32 column, size_t len, u8 *rbuf)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ cmd.cmd = SPINAND_CMD_READ_RDM;
+ cmd.n_addr = 3;
+ cmd.addr[0] = 0;
+ cmd.addr[1] = (u8)(column >> 8);
+ if (chip->options & SPINAND_NEED_PLANE_SELECT)
+ cmd.addr[1] |= (u8)(((page_addr >>
+ (chip->block_shift - chip->page_shift)) & 0x1) << 4);
+ cmd.addr[2] = (u8)column;
+ cmd.n_rx = len;
+ cmd.rx_buf = rbuf;
+
+ return spi_nand_send_cmd(spi, &cmd);
+}
+EXPORT_SYMBOL(spi_nand_read_from_cache_snor_protocol);
+
+/*
+ * spi_nand_program_data_to_cache--to write a page to cache
+ * @chip: SPI-NAND device structure
+ * @page_addr: page to write
+ * @column: the location to write to the cache
+ * @len: number of bytes to write
+ * wrbuf: buffer held @len bytes
+ *
+ * Description:
+ * The write command used here is 0x02--indicating that the cache is
+ * cleared first.
+ * Since it is writing the data to cache, there is no tPROG time.
+ */
+static int spi_nand_program_data_to_cache(struct spi_nand_chip *chip,
+ u32 page_addr, u32 column, size_t len, u8 *wbuf)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ cmd.cmd = SPINAND_CMD_PROG_LOAD;
+ cmd.n_addr = 2;
+ cmd.addr[0] = (u8)(column >> 8);
+ if (chip->options & SPINAND_NEED_PLANE_SELECT)
+ cmd.addr[0] |= (u8)(((page_addr >>
+ (chip->block_shift - chip->page_shift)) & 0x1) << 4);
+ cmd.addr[1] = (u8)column;
+ cmd.n_tx = len;
+ cmd.tx_buf = wbuf;
+ fh_dev_debug(&spi->dev, "see n_tx %d, oob[4] 0x%08x\n",
+ len, *(uint32_t*)(wbuf+2048));
+
+ return spi_nand_send_cmd(spi, &cmd);
+}
+
+/**
+ * spi_nand_program_execute--to write a page from cache to the Nand array
+ * @chip: SPI-NAND device structure
+ * @page_addr: the physical page location to write the page.
+ *
+ * Description:
+ * The write command used here is 0x10--indicating the cache is writing to
+ * the Nand array.
+ * Need to wait for tPROG time to finish the transaction.
+ */
+static int spi_nand_program_execute(struct spi_nand_chip *chip, u32 page_addr)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+ cmd.cmd = SPINAND_CMD_PROG;
+ cmd.n_addr = 3;
+ cmd.addr[0] = (u8)(page_addr >> 16);
+ cmd.addr[1] = (u8)(page_addr >> 8);
+ cmd.addr[2] = (u8)page_addr;
+
+
+ return spi_nand_send_cmd(spi, &cmd);
+}
+
+
+/**
+ * spi_nand_erase_block_erase--to erase a block
+ * @chip: SPI-NAND device structure
+ * @page_addr: the page to erase.
+ *
+ * Description:
+ * The command used here is 0xd8--indicating an erase command to erase
+ * one block
+ * Need to wait for tERS.
+ */
+static int spi_nand_erase_block(struct spi_nand_chip *chip,
+ u32 page_addr)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ cmd.cmd = SPINAND_CMD_ERASE_BLK;
+ cmd.n_addr = 3;
+ cmd.addr[0] = (u8)(page_addr >> 16);
+ cmd.addr[1] = (u8)(page_addr >> 8);
+ cmd.addr[2] = (u8)page_addr;
+
+ return spi_nand_send_cmd(spi, &cmd);
+}
+
+/**
+ * spi_nand_wait - [DEFAULT] wait until the command is done
+ * @chip: SPI-NAND device structure
+ * @s: buffer to store status register(can be NULL)
+ *
+ * Wait for command done. This applies to erase and program only. Erase can
+ * take up to 400ms and program up to 20ms.
+ */
+static int spi_nand_wait(struct spi_nand_chip *chip, u8 *s)
+{
+ unsigned long timeo = jiffies;
+ u8 status, state = chip->state;
+ int ret = -ETIMEDOUT;
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+
+ if (state == FL_ERASING)
+ timeo += msecs_to_jiffies(400);
+ else
+ timeo += msecs_to_jiffies(1000); // 20 -> 40 for mx2g
+
+ while (time_before(jiffies, timeo)) {
+ spi_nand_read_status(chip->spi, &status);
+ if ((status & STATUS_OIP_MASK) == STATUS_READY) {
+ ret = 0;
+ goto out;
+ }
+ cond_resched();
+ }
+out:
+ if (s)
+ *s = status;
+
+ return 0;
+}
+
+
+/*
+ * spi_nand_reset- send RESET command "0xff" to the SPI-NAND.
+ * @chip: SPI-NAND device structure
+ */
+static int spi_nand_reset(struct spi_nand_chip *chip)
+{
+ struct spi_nand_cmd cmd = {0};
+ struct spi_device *spi = chip->spi;
+ fh_dev_debug(&spi->dev, "Enter %s\n", __func__);
+
+ cmd.cmd = SPINAND_CMD_RESET;
+
+ if (spi_nand_send_cmd(spi, &cmd) < 0)
+ pr_err("spi_nand reset failed!\n");
+
+ /* elapse 1ms before issuing any other command */
+ udelay(1000);
+
+ return 0;
+}
+
+
+/**
+ * spi_nand_lock_block- send write register 0x1f command to the lock/unlock device
+ * @spi: spi device structure
+ * @lock: value to set to block lock register
+ *
+ * Description:
+ * After power up, all the Nand blocks are locked. This function allows
+ * one to unlock the blocks, and so it can be written or erased.
+ */
+static int spi_nand_lock_block(struct spi_device *spi, u8 lock)
+{
+ struct spi_nand_cmd cmd = {0};
+ int ret;
+
+ cmd.cmd = SPINAND_CMD_WRITE_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_BLOCK_LOCK;
+ cmd.n_tx = 1;
+ cmd.tx_buf = &lock;
+
+ ret = spi_nand_send_cmd(spi, &cmd);
+ if (ret < 0)
+ dev_err(&spi->dev, "error %d lock block\n", ret);
+
+ return ret;
+}
+
+static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
+{
+ int i;
+
+ while (len--) {
+ crc ^= *p++ << 8;
+ for (i = 0; i < 8; i++)
+ crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+ }
+
+ return crc;
+}
+
+/* Sanitize ONFI strings so we can safely print them */
+static void sanitize_string(uint8_t *s, size_t len)
+{
+ ssize_t i;
+
+ /* Null terminate */
+ s[len - 1] = 0;
+
+ /* Remove non printable chars */
+ for (i = 0; i < len - 1; i++) {
+ if (s[i] < ' ' || s[i] > 127)
+ s[i] = '?';
+ }
+
+ /* Remove trailing spaces */
+ strim(s);
+}
+
+/*
+ * Check if the SPI-NAND chip is ONFI compliant,
+ * returns 1 if it is, 0 otherwise.
+ */
+static bool spi_nand_detect_onfi(struct spi_nand_chip *chip)
+{
+ struct spi_device *spi = chip->spi;
+ struct spi_nand_onfi_params *p;
+ char *buffer;
+ bool ret = true;
+ u8 otp;
+ int i;
+
+ /*FIXME buffer size*/
+ buffer = kmalloc(256 * 3, GFP_KERNEL);
+ otp = OTP_ENABLE;
+ spi_nand_set_otp(spi, &otp);
+ chip->load_page(chip, 0x01);
+ chip->waitfunc(chip, NULL);
+ spi_nand_read_from_cache(chip, 0x01, 0x00, 256 * 3, buffer);
+ otp = OTP_ECC_ENABLE;
+ spi_nand_set_otp(spi, &otp);
+
+ p = (struct spi_nand_onfi_params *)buffer;
+ for (i = 0; i < 3; i++, p++) {
+ if (p->sig[0] != 'O' || p->sig[1] != 'N' ||
+ p->sig[2] != 'F' || p->sig[3] != 'I')
+ continue;
+ if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
+ le16_to_cpu(p->crc))
+ break;
+ }
+ if (i == 3) {
+ pr_err("Could not find valid ONFI parameter page; aborting\n");
+ ret = false;
+ goto out;
+ }
+
+ memcpy(&chip->onfi_params, p, sizeof(*p));
+
+ p = &chip->onfi_params;
+
+ sanitize_string(p->manufacturer, sizeof(p->manufacturer));
+ sanitize_string(p->model, sizeof(p->model));
+
+ chip->name = p->model;
+ chip->size = le32_to_cpu(p->byte_per_page) *
+ le32_to_cpu(p->pages_per_block) *
+ le32_to_cpu(p->blocks_per_lun) * p->lun_count;
+ chip->block_size = le32_to_cpu(p->byte_per_page) *
+ le32_to_cpu(p->pages_per_block);
+ chip->page_size = le32_to_cpu(p->byte_per_page);
+ chip->page_spare_size = le16_to_cpu(p->spare_bytes_per_page);
+ chip->block_shift = ilog2(chip->block_size);
+ chip->page_shift = ilog2(chip->page_size);
+ chip->page_mask = chip->page_size - 1;
+ chip->bits_per_cell = p->bits_per_cell;
+ /*FIXME need to find a way to read options from ONFI table*/
+ chip->options = SPINAND_NEED_PLANE_SELECT;
+ if (p->ecc_bits != 0xff) {
+ chip->ecc_strength_ds = p->ecc_bits;
+ chip->ecc_step_ds = 512;
+ }
+
+out:
+ kfree(buffer);
+ return ret;
+}
+
+static void spi_nand_set_defaults(struct spi_nand_chip *chip)
+{
+ /*struct spi_device *spi = chip->spi;*/
+
+ /* if (spi->mode & SPI_RX_QUAD)
+ chip->read_cache = spi_nand_read_from_cache_x4;
+ else if (spi->mode & SPI_RX_DUAL)
+ chip->read_cache = spi_nand_read_from_cache_x2;
+ else*/
+ chip->read_cache = spi_nand_read_from_cache;
+
+ if (!chip->reset)
+ chip->reset = spi_nand_reset;
+ if (!chip->erase_block)
+ chip->erase_block = spi_nand_erase_block;
+ if (!chip->load_page)
+ chip->load_page = spi_nand_read_page_to_cache;
+ if (!chip->store_cache)
+ chip->store_cache = spi_nand_program_data_to_cache;
+ if (!chip->write_page)
+ chip->write_page = spi_nand_program_execute;
+ if (!chip->write_enable)
+ chip->write_enable = spi_nand_write_enable;
+ if (!chip->waitfunc)
+ chip->waitfunc = spi_nand_wait;
+ if (!chip->enable_ecc)
+ chip->enable_ecc = spi_nand_enable_ecc;
+ if (!chip->disable_ecc)
+ chip->disable_ecc = spi_nand_disable_ecc;
+ if (!chip->block_bad)
+ chip->block_bad = spi_nand_block_checkbad;
+ if (!chip->set_qe)
+ chip->set_qe = spi_nand_set_qe;
+}
+
+static int spi_nand_check(struct spi_nand_chip *chip)
+{
+ if (!chip->reset)
+ return -ENODEV;
+ if (!chip->read_id)
+ return -ENODEV;
+ if (!chip->load_page)
+ return -ENODEV;
+ if (!chip->read_cache)
+ return -ENODEV;
+ if (!chip->store_cache)
+ return -ENODEV;
+ if (!chip->write_page)
+ return -ENODEV;
+ if (!chip->erase_block)
+ return -ENODEV;
+ if (!chip->waitfunc)
+ return -ENODEV;
+ if (!chip->write_enable)
+ return -ENODEV;
+ if (!chip->get_ecc_status)
+ return -ENODEV;
+ if (!chip->enable_ecc)
+ return -ENODEV;
+ if (!chip->disable_ecc)
+ return -ENODEV;
+ if (!chip->ecclayout)
+ return -ENODEV;
+ return 0;
+}
+
+/**
+ * spi_nand_scan_ident - [SPI-NAND Interface] Scan for the SPI-NAND device
+ * @mtd: MTD device structure
+ *
+ * This is the first phase of the normal spi_nand_scan() function. It reads the
+ * flash ID and sets up MTD fields accordingly.
+ *
+ */
+int spi_nand_scan_ident(struct mtd_info *mtd)
+{
+ int ret;
+ u8 id[SPINAND_MAX_ID_LEN] = {0};
+ struct spi_nand_chip *chip = mtd->priv;
+
+ spi_nand_set_defaults(chip);
+ chip->reset(chip);
+
+ chip->read_id_dummy = SPI_NAND_ID_DUMMY;
+ chip->read_id(chip, id);
+
+ pr_debug("SPINAND: read id ! 0x%02x, 0x%02x 0x%02x, 0x%02x!\n",
+ id[0], id[1], id[2], id[3]);
+ if (spi_nand_scan_id_table(chip, id))
+ goto ident_done;
+
+ chip->read_id_dummy = SPI_NAND_ID_NO_DUMMY;
+ chip->read_id(chip, id);
+
+ pr_debug("SPINAND: read id ! 0x%02x, 0x%02x 0x%02x, 0x%02x!\n",
+ id[0], id[1], id[2], id[3]);
+ if (spi_nand_scan_id_table(chip, id))
+ goto ident_done;
+
+ pr_info("SPI-NAND type mfr_id: %x, dev_id: %x is not in id table.\n",
+ id[0], id[1]);
+
+ if (spi_nand_detect_onfi(chip))
+ goto ident_done;
+
+ return -ENODEV;
+
+ident_done:
+ pr_info("SPI-NAND: %s is found.\n", chip->name);
+
+ if (chip->spi->mode & SPI_RX_QUAD)
+ chip->set_qe(chip);
+
+ chip->buf = kzalloc(chip->page_size + chip->page_spare_size,
+ GFP_KERNEL);
+ if (!chip->buf)
+ return -ENOMEM;
+
+ chip->oobbuf = chip->buf + chip->page_size;
+
+ ret = spi_nand_lock_block(chip->spi, BL_ALL_UNLOCKED);
+ ret = chip->enable_ecc(chip);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(spi_nand_scan_ident);
+
+/**
+ * spi_nand_scan_tail - [SPI-NAND Interface] Scan for the SPI-NAND device
+ * @mtd: MTD device structure
+ *
+ * This is the second phase of the normal spi_nand_scan() function. It fills out
+ * all the uninitialized function pointers with the defaults.
+ */
+int spi_nand_scan_tail(struct mtd_info *mtd)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+ int ret;
+
+ ret = spi_nand_check(chip);
+ if (ret)
+ return ret;
+ /* Initialize state */
+ chip->state = FL_READY;
+ /* Invalidate the pagebuffer reference */
+ chip->pagebuf = -1;
+ chip->bbt_options |= NAND_BBT_USE_FLASH;
+ chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
+
+ init_waitqueue_head(&chip->wq);
+ spin_lock_init(&chip->chip_lock);
+
+ /*mtd->name = chip->name;*/
+ mtd->size = chip->size;
+ mtd->erasesize = chip->block_size;
+ mtd->writesize = chip->page_size;
+ mtd->writebufsize = mtd->writesize;
+ mtd->oobsize = chip->page_spare_size;
+ mtd->owner = THIS_MODULE;
+ mtd->type = MTD_NANDFLASH;
+ mtd->flags = MTD_CAP_NANDFLASH;
+ mtd->ecc_strength = chip->ecc_strength_ds ?
+ chip->ecc_strength_ds : 1;
+ mtd->bitflip_threshold = chip->bitflip_threshold ?
+ chip->bitflip_threshold : 1;
+ //mtd->_ecclayout = chip->ecclayout;
+ mtd->oobsize = chip->page_spare_size;
+ mtd->oobavail = chip->ecclayout->oobavail;
+ /* remove _* */
+ mtd->_erase = spi_nand_erase;
+ mtd->_point = NULL;
+ mtd->_unpoint = NULL;
+ mtd->_read = spi_nand_read;
+ mtd->_write = spi_nand_write;
+ mtd->_read_oob = spi_nand_read_oob;
+ mtd->_write_oob = spi_nand_write_oob;
+ mtd->_sync = spi_nand_sync;
+ mtd->_lock = NULL;
+ mtd->_unlock = NULL;
+ mtd->_suspend = spi_nand_suspend;
+ mtd->_resume = spi_nand_resume;
+ mtd->_block_isbad = spi_nand_block_isbad;
+ mtd->_block_markbad = spi_nand_block_markbad;
+
+#ifndef CONFIG_SPI_NAND_BBT
+ /* Build bad block table */
+ return spi_nand_default_bbt(mtd);
+#else
+ return 0;
+#endif
+}
+EXPORT_SYMBOL_GPL(spi_nand_scan_tail);
+
+/**
+ * spi_nand_scan_ident_release - [SPI-NAND Interface] Free resources
+ * applied by spi_nand_scan_ident
+ * @mtd: MTD device structure
+ */
+int spi_nand_scan_ident_release(struct mtd_info *mtd)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+
+ kfree(chip->buf);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_nand_scan_ident_release);
+
+/**
+ * spi_nand_scan_tail_release - [SPI-NAND Interface] Free resources
+ * applied by spi_nand_scan_tail
+ * @mtd: MTD device structure
+ */
+int spi_nand_scan_tail_release(struct mtd_info *mtd)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_nand_scan_tail_release);
+
+/**
+ * spi_nand_release - [SPI-NAND Interface] Free resources held by the SPI-NAND
+ * device
+ * @mtd: MTD device structure
+ */
+int spi_nand_release(struct mtd_info *mtd)
+{
+ struct spi_nand_chip *chip = mtd->priv;
+
+ mtd_device_unregister(mtd);
+ kfree(chip->buf);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_nand_release);
+
+
+MODULE_DESCRIPTION("SPI NAND framework");
+MODULE_AUTHOR("Peter Pan<peterpandong at micron.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/mtd/spi-nand/spi-nand-bbt.c b/drivers/mtd/spi-nand/spi-nand-bbt.c
new file mode 100644
index 00000000..9ae84507
--- /dev/null
+++ b/drivers/mtd/spi-nand/spi-nand-bbt.c
@@ -0,0 +1,1362 @@
+/*
+ * drivers/mtd/spi_nand_bbt.c
+ *
+ * Overview:
+ * Bad block table support for the SPI-NAND driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file is derived from nand_base.c
+ *
+ * TODO:
+ * share BBT code with parallel nand
+ */
+
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/bbm.h>
+#include <linux/mtd/spi-nand.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/spi/spi.h>
+#include <asm/string.h>
+
+#define BBT_BLOCK_GOOD 0x00
+#define BBT_BLOCK_WORN 0x01
+#define BBT_BLOCK_RESERVED 0x02
+#define BBT_BLOCK_FACTORY_BAD 0x03
+
+#define BBT_ENTRY_MASK 0x03
+#define BBT_ENTRY_SHIFT 2
+
+#ifdef SPINAND_BBT_DEBUG
+#define fh_dev_debug dev_err
+#define fh_debug_dump(buf,len) do { \
+ unsigned int i; \
+ printk("\t %s:L%d", __func__,__LINE__); \
+ for (i=0;i<len/4;i++) { \
+ if (0 == i % 4 ) \
+ printk("\n\t\t 0x%08x:\t",(unsigned int) buf+i*4 ); \
+ printk("%08x ", *(unsigned int*) (buf + i*4));\
+ } \
+ } while(0)
+#else
+#define fh_dev_debug(...)
+#define fh_debug_dump(buf,len)
+#endif
+
+
+static int spi_nand_update_bbt(struct mtd_info *mtd, loff_t offs);
+
+static inline uint8_t bbt_get_entry(struct spi_nand_chip *chip, int block)
+{
+ uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT];
+
+ entry >>= (block & BBT_ENTRY_MASK) * 2;
+ return entry & BBT_ENTRY_MASK;
+}
+
+static inline void bbt_mark_entry(struct spi_nand_chip *chip, int block,
+ uint8_t mark)
+{
+ uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2);
+
+ chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk;
+}
+
+static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td)
+{
+ if (memcmp(buf, td->pattern, td->len))
+ return -1;
+ return 0;
+}
+
+/**
+ * check_pattern - [GENERIC] check if a pattern is in the buffer
+ * @buf: the buffer to search
+ * @len: the length of buffer to search
+ * @paglen: the pagelength
+ * @td: search pattern descriptor
+ *
+ * Check for a pattern at the given place. Used to search bad block tables and
+ * good / bad block identifiers.
+ */
+static int check_pattern(uint8_t *buf, int len, int paglen,
+ struct nand_bbt_descr *td)
+{
+ if (td->options & NAND_BBT_NO_OOB)
+ return check_pattern_no_oob(buf, td);
+
+ /* Compare the pattern */
+ fh_debug_dump(buf + paglen + td->offs, td->len);
+ if (memcmp(buf + paglen + td->offs, td->pattern, td->len))
+ return -1;
+
+ return 0;
+}
+
+/**
+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+ * @buf: the buffer to search
+ * @td: search pattern descriptor
+ *
+ * Check for a pattern at the given place. Used to search bad block tables and
+ * good / bad block identifiers. Same as check_pattern, but no optional empty
+ * check.
+ */
+static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
+{
+ /* Compare the pattern */
+ if (memcmp(buf + td->offs, td->pattern, td->len))
+ return -1;
+ return 0;
+}
+
+/**
+ * add_marker_len - compute the length of the marker in data area
+ * @td: BBT descriptor used for computation
+ *
+ * The length will be 0 if the marker is located in OOB area.
+ */
+static u32 add_marker_len(struct nand_bbt_descr *td)
+{
+ u32 len;
+
+ if (!(td->options & NAND_BBT_NO_OOB))
+ return 0;
+
+ len = td->len;
+ if (td->options & NAND_BBT_VERSION)
+ len++;
+ return len;
+}
+
+#if 0
+static inline int mtd_is_eccerr(int err)
+{
+ return err == -EBADMSG;
+}
+
+static inline int mtd_is_bitflip(int err)
+{
+ return err == -EUCLEAN;
+}
+
+static inline int mtd_is_bitflip_or_eccerr(int err)
+{
+ return mtd_is_bitflip(err) || mtd_is_eccerr(err);
+}
+#endif
+/**
+ * read_bbt - [GENERIC] Read the bad block table starting from page
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @page: the starting page
+ * @num: the number of bbt descriptors to read
+ * @td: the bbt describtion table
+ * @offs: block number offset in the table
+ *
+ * Read the bad block table starting from page.
+ */
+static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
+ struct nand_bbt_descr *td, int offs)
+{
+ int res, ret = 0, i, j, act = 0;
+ struct spi_nand_chip *this = mtd->priv;
+ size_t retlen, len, totlen;
+ loff_t from;
+ int bits = td->options & NAND_BBT_NRBITS_MSK;
+ uint8_t msk = (uint8_t)((1 << bits) - 1);
+ u32 marker_len;
+ int reserved_block_code = td->reserved_block_code;
+
+ totlen = (num * bits) >> 3;
+ marker_len = add_marker_len(td);
+ from = ((loff_t)page) << this->page_shift;
+
+ while (totlen) {
+ len = min(totlen, (size_t)(1 << this->block_shift));
+ if (marker_len) {
+ /*
+ * In case the BBT marker is not in the OOB area it
+ * will be just in the first page.
+ */
+ len -= marker_len;
+ from += marker_len;
+ marker_len = 0;
+ }
+ res = mtd->_read(mtd, from, len, &retlen,
+ buf); /*/// mtd_read(mtd, from, len, &retlen, buf);*/
+ if (res < 0) {
+ if (mtd_is_eccerr(res)) {
+ pr_info("spi_nand_bbt: ECC error in BBT at 0x%012llx\n",
+ from & ~mtd->writesize);
+ return res;
+ } else if (mtd_is_bitflip(res)) {
+ pr_info("spi_nand_bbt: corrected error in BBT at 0x%012llx\n",
+ from & ~mtd->writesize);
+ ret = res;
+ } else {
+ pr_info("spi_nand_bbt: error reading BBT\n");
+ return res;
+ }
+ }
+
+ /* Analyse data */
+ for (i = 0; i < len; i++) {
+ uint8_t dat = buf[i];
+
+ for (j = 0; j < 8; j += bits, act++) {
+ uint8_t tmp = (dat >> j) & msk;
+
+ if (tmp == msk)
+ continue;
+ if (reserved_block_code &&
+ (tmp == reserved_block_code)) {
+ pr_info("spi_nand_read_bbt: reserved block at 0x%012llx\n",
+ (loff_t)(offs + act) <<
+ this->block_shift);
+ bbt_mark_entry(this, offs + act,
+ BBT_BLOCK_RESERVED);
+ mtd->ecc_stats.bbtblocks++;
+ continue;
+ }
+ /*
+ * Leave it for now, if it's matured we can
+ * move this message to pr_debug.
+ */
+ pr_info("spi_nand_read_bbt: bad block at 0x%012llx\n",
+ (loff_t)(offs + act) <<
+ this->block_shift);
+ /* Factory marked bad or worn out? */
+ if (tmp == 0)
+ bbt_mark_entry(this, offs + act,
+ BBT_BLOCK_FACTORY_BAD);
+ else
+ bbt_mark_entry(this, offs + act,
+ BBT_BLOCK_WORN);
+ mtd->ecc_stats.badblocks++;
+ }
+ }
+ totlen -= len;
+ from += len;
+ }
+ return ret;
+}
+
+/**
+ * read_abs_bbt - [GENERIC] Read the bad block table starting at a given page
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @chip: read the table for a specific chip, -1 read all chips; applies only if
+ * NAND_BBT_PERCHIP option is set
+ *
+ * Read the bad block table for all chips starting at a given page. We assume
+ * that the bbt bits are in consecutive order.
+ */
+static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *td, int chip)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int res = 0;
+
+ res = read_bbt(mtd, buf, td->pages[0],
+ mtd->size >> this->block_shift, td, 0);
+ if (res)
+ return res;
+
+ return 0;
+}
+
+/* BBT marker is in the first page, no OOB */
+static int scan_read_data(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+ struct nand_bbt_descr *td)
+{
+ size_t retlen;
+ size_t len;
+
+ len = td->len;
+ if (td->options & NAND_BBT_VERSION)
+ len++;
+
+ /*return mtd_read(mtd, offs, len, &retlen, buf);*/
+ return mtd->_read(mtd, offs, len, &retlen, buf);
+}
+
+/**
+ * scan_read_oob - [GENERIC] Scan data+OOB region to buffer
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @offs: offset at which to scan
+ * @len: length of data region to read
+ *
+ * Scan read data from data+OOB. May traverse multiple pages, interleaving
+ * page,OOB,page,OOB,... in buf. Completes transfer and returns the "strongest"
+ * ECC condition (error or bitflip). May quit on the first (non-ECC) error.
+ */
+static int scan_read_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+ size_t len)
+{
+ struct mtd_oob_ops ops;
+ int res, ret = 0;
+#ifdef SPINAND_BBT_DEBUG
+ struct spi_nand_chip *chip = mtd->priv;
+ fh_dev_debug(&chip->spi->dev, "Enter %s\n", __func__);
+#endif
+ ops.mode = MTD_OOB_PLACE;
+ ops.ooboffs = 0;
+ ops.ooblen = mtd->oobsize;
+
+ while (len > 0) {
+ ops.datbuf = buf;
+ ops.len = min_t(size_t, len, mtd->writesize);
+ ops.oobbuf = buf + ops.len;
+
+ /*res = mtd_read_oob(mtd, offs, &ops);*/
+ res = mtd->_read_oob(mtd, offs, &ops);
+ if (res) {
+ if (!mtd_is_bitflip_or_eccerr(res))
+ return res;
+ else if (mtd_is_eccerr(res) || !ret)
+ ret = res;
+ }
+
+ buf += mtd->oobsize + mtd->writesize;
+ len -= mtd->writesize;
+ offs += mtd->writesize;
+ }
+ return ret;
+}
+
+static int scan_read(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+ size_t len, struct nand_bbt_descr *td)
+{
+ if (td->options & NAND_BBT_NO_OOB)
+ return scan_read_data(mtd, buf, offs, td);
+ else
+ return scan_read_oob(mtd, buf, offs, len);
+}
+
+/* Scan write data with oob to flash */
+static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
+ uint8_t *buf, uint8_t *oob)
+{
+ struct mtd_oob_ops ops;
+
+ ops.mode = MTD_OOB_PLACE;
+ ops.ooboffs = 0;
+ ops.ooblen = mtd->oobsize;
+ ops.datbuf = buf;
+ ops.oobbuf = oob;
+ ops.len = len;
+
+ /*return mtd_write_oob(mtd, offs, &ops);*/
+ return mtd->_write_oob(mtd, offs, &ops);
+}
+
+static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
+{
+ u32 ver_offs = td->veroffs;
+
+ if (!(td->options & NAND_BBT_NO_OOB))
+ ver_offs += mtd->writesize;
+ return ver_offs;
+}
+
+/**
+ * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md: descriptor for the bad block table mirror
+ *
+ * Read the bad block table(s) for all chips starting at a given page. We
+ * assume that the bbt bits are in consecutive order.
+ */
+static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *td, struct nand_bbt_descr *md)
+{
+ struct spi_nand_chip *this = mtd->priv;
+
+ /* Read the primary version, if available */
+ if (td->options & NAND_BBT_VERSION) {
+ scan_read(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
+ mtd->writesize, td);
+ td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
+ pr_info("Bad block table at page %d, version 0x%02X\n",
+ td->pages[0], td->version[0]);
+ }
+
+ /* Read the mirror version, if available */
+ if (md && (md->options & NAND_BBT_VERSION)) {
+ scan_read(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
+ mtd->writesize, md);
+ md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
+ pr_info("Bad block table at page %d, version 0x%02X\n",
+ md->pages[0], md->version[0]);
+ }
+}
+
+/* Scan a given block partially */
+static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+ loff_t offs, uint8_t *buf, int numpages)
+{
+ struct mtd_oob_ops ops;
+ int j, ret;
+
+ ops.ooblen = mtd->oobsize;
+ ops.oobbuf = buf;
+ ops.ooboffs = 0;
+ ops.datbuf = NULL;
+ ops.mode = MTD_OOB_PLACE;
+
+ for (j = 0; j < numpages; j++) {
+ /*
+ * Read the full oob until read_oob is fixed to handle single
+ * byte reads for 16 bit buswidth.
+ */
+ ret = mtd->_read_oob(mtd, offs, &ops);/*mtd_read_oob(mtd, offs, &ops);*/
+ /* Ignore ECC errors when checking for BBM */
+ if (ret < 0 && !mtd_is_bitflip_or_eccerr(ret))
+ return ret;
+
+ if (mtd_is_eccerr(ret))
+ return 1;
+
+ if (check_short_pattern(buf, bd))
+ return 1;
+
+ offs += mtd->writesize;
+ }
+ return 0;
+}
+
+/**
+ * create_bbt - [GENERIC] Create a bad block table by scanning the device
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @bd: descriptor for the good/bad block search pattern
+ * @chip: create the table for a specific chip, -1 read all chips; applies only
+ * if NAND_BBT_PERCHIP option is set
+ *
+ * Create a bad block table by scanning the device for the given good/bad block
+ * identify pattern.
+ */
+static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *bd, int chip)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int i, numblocks, numpages;
+ int startblock;
+ loff_t from;
+ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__);
+
+ pr_info("Scanning device for bad blocks\n");
+
+ if (bd->options & NAND_BBT_SCAN2NDPAGE)
+ numpages = 2;
+ else
+ numpages = 1;
+
+ if (chip == -1) {
+ numblocks = mtd->size >> this->block_shift;
+ startblock = 0;
+ from = 0;
+ } else {
+ numblocks = this->size >> this->block_shift;
+ startblock = chip * numblocks;
+ numblocks += startblock;
+ from = (loff_t)startblock << this->block_shift;
+ }
+
+ if (this->bbt_options & NAND_BBT_SCANLASTPAGE)
+ from += mtd->erasesize - (mtd->writesize * numpages);
+
+ for (i = startblock; i < numblocks; i++) {
+ int ret;
+
+ BUG_ON(bd->options & NAND_BBT_NO_OOB);
+
+ ret = scan_block_fast(mtd, bd, from, buf, numpages);
+ if (ret < 0)
+ return ret;
+
+ if (ret) {
+ bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD);
+ pr_warn("Bad eraseblock %d at 0x%012llx\n",
+ i, (unsigned long long)from);
+ mtd->ecc_stats.badblocks++;
+ }
+
+ from += (1 << this->block_shift);
+ }
+ return 0;
+}
+
+/**
+ * search_bbt - [GENERIC] scan the device for a specific bad block table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ *
+ * Read the bad block table by searching for a given ident pattern. Search is
+ * preformed either from the beginning up or from the end of the device
+ * downwards. The search starts always at the start of a block. If the option
+ * NAND_BBT_PERCHIP is given, each chip is searched for a bbt, which contains
+ * the bad block information of this chip. This is necessary to provide support
+ * for certain DOC devices.
+ *
+ * The bbt ident pattern resides in the oob area of the first page in a block.
+ */
+static int search_bbt(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *td)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int i, chips;
+ int startblock, block, dir;
+ int scanlen = mtd->writesize + mtd->oobsize;
+ int bbtblocks;
+ int blocktopage = this->block_shift - this->page_shift;
+
+ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__);
+ /* Search direction top -> down? */
+ if (td->options & NAND_BBT_LASTBLOCK) {
+ startblock = (mtd->size >> this->block_shift) - 1;
+ dir = -1;
+ } else {
+ startblock = 0;
+ dir = 1;
+ }
+
+ chips = 1;
+ bbtblocks = mtd->size >> this->block_shift;
+
+ for (i = 0; i < chips; i++) {
+ /* Reset version information */
+ td->version[i] = 0;
+ td->pages[i] = -1;
+ /* Scan the maximum number of blocks */
+ for (block = 0; block < td->maxblocks; block++) {
+
+ int actblock = startblock + dir * block;
+ loff_t offs = (loff_t)actblock << this->block_shift;
+
+ /* Read first page */
+ scan_read(mtd, buf, offs, mtd->writesize, td);
+ fh_dev_debug(&this->spi->dev, "read block %d, first v 0x%08x\n ",
+ actblock, *(int *)buf);
+ fh_dev_debug(&this->spi->dev, "td pattern:%s, offset %d, len %d\n ",
+ td->pattern, td->offs,td->len);
+ if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
+ td->pages[i] = actblock << blocktopage;
+ if (td->options & NAND_BBT_VERSION) {
+ offs = bbt_get_ver_offs(mtd, td);
+ td->version[i] = buf[offs];
+ }
+ break;
+ }
+ }
+ startblock += this->size >> this->block_shift;
+ }
+ /* Check, if we found a bbt for each requested chip */
+ for (i = 0; i < chips; i++) {
+ if (td->pages[i] == -1)
+ pr_warn("Bad block table not found for chip %d\n", i);
+ else
+ pr_info("Bad block table found at page %d, version 0x%02X\n",
+ td->pages[i], td->version[i]);
+ }
+ return 0;
+}
+
+/**
+ * search_read_bbts - [GENERIC] scan the device for bad block table(s)
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md: descriptor for the bad block table mirror
+ *
+ * Search and read the bad block table(s).
+ */
+static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *td,
+ struct nand_bbt_descr *md)
+{
+ /* Search the primary table */
+ search_bbt(mtd, buf, td);
+
+ /* Search the mirror table */
+ if (md)
+ search_bbt(mtd, buf, md);
+}
+
+/**
+ * write_bbt - [GENERIC] (Re)write the bad block table
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @td: descriptor for the bad block table
+ * @md: descriptor for the bad block table mirror
+ * @chipsel: selector for a specific chip, -1 for all
+ *
+ * (Re)write the bad block table.
+ */
+static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *td, struct nand_bbt_descr *md,
+ int chipsel)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ struct erase_info einfo;
+ int i, res, chip = 0;
+ int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
+ int nrchips, pageoffs, ooboffs;
+ uint8_t msk[4];
+ uint8_t rcode = td->reserved_block_code;
+ size_t retlen, len = 0;
+ loff_t to;
+ struct mtd_oob_ops ops;
+ extern int fh_start_debug;
+ fh_start_debug = 1;
+ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__);
+
+ ops.ooblen = mtd->oobsize;
+ ops.ooboffs = 0;
+ ops.datbuf = NULL;
+ ops.mode = MTD_OOB_PLACE;
+
+ if (!rcode)
+ rcode = 0xff;
+ numblocks = (int)(mtd->size >> this->block_shift);
+ nrchips = 1;
+
+ /* Loop through the chips */
+ for (; chip < nrchips; chip++) {
+ /*
+ * There was already a version of the table, reuse the page
+ * This applies for absolute placement too, as we have the
+ * page nr. in td->pages.
+ */
+ if (td->pages[chip] != -1) {
+ page = td->pages[chip];
+ goto write;
+ }
+
+ /*
+ * Automatic placement of the bad block table. Search direction
+ * top -> down?
+ */
+ if (td->options & NAND_BBT_LASTBLOCK) {
+ startblock = numblocks * (chip + 1) - 1;
+ dir = -1;
+ } else {
+ startblock = chip * numblocks;
+ dir = 1;
+ }
+
+ for (i = 0; i < td->maxblocks; i++) {
+ int block = startblock + dir * i;
+ /* Check, if the block is bad */
+ switch (bbt_get_entry(this, block)) {
+ case BBT_BLOCK_WORN:
+ case BBT_BLOCK_FACTORY_BAD:
+ continue;
+ }
+ page = block <<
+ (this->block_shift - this->page_shift);
+ /* Check, if the block is used by the mirror table */
+ if (!md || md->pages[chip] != page)
+ goto write;
+ }
+ pr_err("No space left to write bad block table\n");
+ return -ENOSPC;
+write:
+
+ /* Set up shift count and masks for the flash table */
+ bits = td->options & NAND_BBT_NRBITS_MSK;
+ msk[2] = ~rcode;
+ switch (bits) {
+ case 1:
+ sft = 3;
+ sftmsk = 0x07;
+ msk[0] = 0x00;
+ msk[1] = 0x01;
+ msk[3] = 0x01;
+ break;
+ case 2:
+ sft = 2;
+ sftmsk = 0x06;
+ msk[0] = 0x00;
+ msk[1] = 0x01;
+ msk[3] = 0x03;
+ break;
+ case 4:
+ sft = 1;
+ sftmsk = 0x04;
+ msk[0] = 0x00;
+ msk[1] = 0x0C;
+ msk[3] = 0x0f;
+ break;
+ case 8:
+ sft = 0;
+ sftmsk = 0x00;
+ msk[0] = 0x00;
+ msk[1] = 0x0F;
+ msk[3] = 0xff;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ to = ((loff_t)page) << this->page_shift;
+
+ fh_dev_debug(&this->spi->dev, " td.options 0x08%x\n", td->options);
+
+ /* Must we save the block contents? */
+ if (td->options & NAND_BBT_SAVECONTENT) {
+ /* Make it block aligned */
+ to &= ~((loff_t)((1 << this->block_shift) - 1));
+ len = 1 << this->block_shift;
+ res = mtd->_read(mtd, to, len, &retlen,
+ buf); // mtd_read(mtd, to, len, &retlen, buf);
+ if (res < 0) {
+ if (retlen != len) {
+ pr_info("spi_nand_bbt: error reading block ");
+ pr_info("for writing the bad block table\n");
+ return res;
+ }
+ pr_warn("spi_nand_bbt: ECC error while reading ");
+ pr_warn("block for writing bad block table\n");
+ }
+ /* Read oob data */
+ ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
+ ops.oobbuf = &buf[len];
+ res = mtd->_read_oob(mtd, to + mtd->writesize,
+ &ops); /*mtd_read_oob(mtd, to + mtd->writesize, &ops);*/
+ if (res < 0 || ops.oobretlen != ops.ooblen)
+ goto outerr;
+
+ /* Calc the byte offset in the buffer */
+ pageoffs = page - (int)(to >> this->page_shift);
+ offs = pageoffs << this->page_shift;
+ /* Preset the bbt area with 0xff */
+ memset(&buf[offs], 0xff, (size_t)(numblocks >> sft));
+ ooboffs = len + (pageoffs * mtd->oobsize);
+
+ } else if (td->options & NAND_BBT_NO_OOB) {
+ ooboffs = 0;
+ offs = td->len;
+ /* The version byte */
+ if (td->options & NAND_BBT_VERSION)
+ offs++;
+ /* Calc length */
+ len = (size_t)(numblocks >> sft);
+ len += offs;
+ /* Make it page aligned! */
+ len = ALIGN(len, mtd->writesize);
+ /* Preset the buffer with 0xff */
+ memset(buf, 0xff, len);
+ /* Pattern is located at the begin of first page */
+ memcpy(buf, td->pattern, td->len);
+ } else {
+ /* Calc length */
+ len = (size_t)(numblocks >> sft);
+ /* Make it page aligned! */
+ len = ALIGN(len, mtd->writesize);
+ /* Preset the buffer with 0xff */
+ memset(buf, 0xff, len +
+ (len >> this->page_shift) * mtd->oobsize);
+ offs = 0;
+ ooboffs = len;
+ /* Pattern is located in oob area of first page */
+ memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
+
+ /*fh_debug_dump(td->pattern, td->len);*/
+ }
+
+ if (td->options & NAND_BBT_VERSION)
+ buf[ooboffs + td->veroffs] = td->version[chip];
+
+ /* Walk through the memory table */
+ for (i = 0; i < numblocks; i++) {
+ uint8_t dat;
+ int sftcnt = (i << (3 - sft)) & sftmsk;
+
+ dat = bbt_get_entry(this, chip * numblocks + i);
+ /* Do not store the reserved bbt blocks! */
+ buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt);
+ }
+
+ memset(&einfo, 0, sizeof(einfo));
+ einfo.mtd = mtd;
+ einfo.addr = to;
+ einfo.len = 1 << this->block_shift;
+ res = __spi_nand_erase(mtd, &einfo, 1);
+ if (res < 0)
+ goto outerr;
+
+ /*fh_debug_dump(&buf[ooboffs],20);*/
+ res = scan_write_bbt(mtd, to, len, buf,
+ td->options & NAND_BBT_NO_OOB ? NULL :
+ &buf[len]);
+
+ if (res < 0)
+ goto outerr;
+
+ pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
+ (unsigned long long)to, td->version[chip]);
+
+ /* Mark it as used */
+ td->pages[chip] = page;
+ }
+ return 0;
+
+outerr:
+ pr_warn("spi_nand_bbt: error while writing bad block table %d\n", res);
+ return res;
+}
+
+/**
+ * spi_nand_memory_bbt - [GENERIC] create a memory based bad block table
+ * @mtd: MTD device structure
+ * @bd: descriptor for the good/bad block search pattern
+ *
+ * The function creates a memory based bbt by scanning the device for
+ * manufacturer / software marked good / bad blocks.
+ */
+static inline int spi_nand_memory_bbt(struct mtd_info *mtd,
+ struct nand_bbt_descr *bd)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__);
+
+ return create_bbt(mtd, this->buf, bd, -1);
+}
+
+/**
+ * check_create - [GENERIC] create and write bbt(s) if necessary
+ * @mtd: MTD device structure
+ * @buf: temporary buffer
+ * @bd: descriptor for the good/bad block search pattern
+ *
+ * The function checks the results of the previous call to read_bbt and creates
+ * / updates the bbt(s) if necessary. Creation is necessary if no bbt was found
+ * for the chip/device. Update is necessary if one of the tables is missing or
+ * the version nr. of one table is less than the other.
+ */
+static int check_create(struct mtd_info *mtd, uint8_t *buf,
+ struct nand_bbt_descr *bd)
+{
+ int i, chips, writeops, create, chipsel, res, res2;
+ struct spi_nand_chip *this = mtd->priv;
+ struct nand_bbt_descr *td = this->bbt_td;
+ struct nand_bbt_descr *md = this->bbt_md;
+ struct nand_bbt_descr *rd, *rd2;
+
+ chips = 1;
+
+ for (i = 0; i < chips; i++) {
+ writeops = 0;
+ create = 0;
+ rd = NULL;
+ rd2 = NULL;
+ res = res2 = 0;
+ /* Per chip or per device? */
+ chipsel = -1;
+ /* Mirrored table available? */
+ if (md) {
+ if (td->pages[i] == -1 && md->pages[i] == -1) {
+ create = 1;
+ writeops = 0x03;
+ } else if (td->pages[i] == -1) {
+ rd = md;
+ writeops = 0x01;
+ } else if (md->pages[i] == -1) {
+ rd = td;
+ writeops = 0x02;
+ } else if (td->version[i] == md->version[i]) {
+ rd = td;
+ if (!(td->options & NAND_BBT_VERSION))
+ rd2 = md;
+ } else if (((int8_t)(td->version[i] - md->version[i]))
+ > 0) {
+ rd = td;
+ writeops = 0x02;
+ } else {
+ rd = md;
+ writeops = 0x01;
+ }
+ } else {
+ if (td->pages[i] == -1) {
+ create = 1;
+ writeops = 0x01;
+ } else
+ rd = td;
+ }
+
+ if (create) {
+ /* Create the bad block table by scanning the device? */
+ if (!(td->options & NAND_BBT_CREATE))
+ continue;
+
+ /* Create the table in memory by scanning the chip(s) */
+ /*xxx: create it; if (!(this->bbt_options & NAND_BBT_CREATE_EMPTY))*/
+ create_bbt(mtd, buf, bd, chipsel);
+
+ td->version[i] = 1;
+ if (md)
+ md->version[i] = 1;
+ }
+
+ /* Read back first? */
+ if (rd) {
+ res = read_abs_bbt(mtd, buf, rd, chipsel);
+ if (mtd_is_eccerr(res)) {
+ /* Mark table as invalid */
+ rd->pages[i] = -1;
+ rd->version[i] = 0;
+ i--;
+ continue;
+ }
+ }
+ /* If they weren't versioned, read both */
+ if (rd2) {
+ res2 = read_abs_bbt(mtd, buf, rd2, chipsel);
+ if (mtd_is_eccerr(res2)) {
+ /* Mark table as invalid */
+ rd2->pages[i] = -1;
+ rd2->version[i] = 0;
+ i--;
+ continue;
+ }
+ }
+
+ /* Scrub the flash table(s)? */
+ if (mtd_is_bitflip(res) || mtd_is_bitflip(res2))
+ writeops = 0x03;
+
+ /* Update version numbers before writing */
+ if (md) {
+ td->version[i] = max(td->version[i], md->version[i]);
+ md->version[i] = td->version[i];
+ }
+
+ /* Write the bad block table to the device? */
+ if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
+ res = write_bbt(mtd, buf, td, md, chipsel);
+ if (res < 0)
+ return res;
+ }
+
+ /* Write the mirror bad block table to the device? */
+ if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
+ res = write_bbt(mtd, buf, md, td, chipsel);
+ if (res < 0)
+ return res;
+ }
+ }
+ return 0;
+}
+
+/**
+ * mark_bbt_regions - [GENERIC] mark the bad block table regions
+ * @mtd: MTD device structure
+ * @td: bad block table descriptor
+ *
+ * The bad block table regions are marked as "bad" to prevent accidental
+ * erasures / writes. The regions are identified by the mark 0x02.
+ */
+static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int i, j, chips, block, nrblocks, update;
+ uint8_t oldval;
+
+ chips = 1;
+ nrblocks = (int)(mtd->size >> this->block_shift);
+
+ for (i = 0; i < chips; i++) {
+ if ((td->options & NAND_BBT_ABSPAGE) ||
+ !(td->options & NAND_BBT_WRITE)) {
+ if (td->pages[i] == -1)
+ continue;
+ block = td->pages[i] >>
+ (this->block_shift - this->page_shift);
+ oldval = bbt_get_entry(this, block);
+ bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
+ if ((oldval != BBT_BLOCK_RESERVED) &&
+ td->reserved_block_code)
+ spi_nand_update_bbt(mtd, (loff_t)block <<
+ this->block_shift);
+ continue;
+ }
+ update = 0;
+ if (td->options & NAND_BBT_LASTBLOCK)
+ block = ((i + 1) * nrblocks) - td->maxblocks;
+ else
+ block = i * nrblocks;
+ for (j = 0; j < td->maxblocks; j++) {
+ oldval = bbt_get_entry(this, block);
+ bbt_mark_entry(this, block, BBT_BLOCK_RESERVED);
+ if (oldval != BBT_BLOCK_RESERVED)
+ update = 1;
+ block++;
+ }
+ /*
+ * If we want reserved blocks to be recorded to flash, and some
+ * new ones have been marked, then we need to update the stored
+ * bbts. This should only happen once.
+ */
+ if (update && td->reserved_block_code)
+ spi_nand_update_bbt(mtd, (loff_t)(block - 1) <<
+ this->block_shift);
+ }
+ fh_dev_debug(&this->spi->dev, "Leave %s\n", __func__);
+}
+
+/**
+ * verify_bbt_descr - verify the bad block description
+ * @mtd: MTD device structure
+ * @bd: the table to verify
+ *
+ * This functions performs a few sanity checks on the bad block description
+ * table.
+ */
+static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ u32 pattern_len;
+ u32 bits;
+ u32 table_size;
+
+ if (!bd)
+ return;
+
+ pattern_len = bd->len;
+ bits = bd->options & NAND_BBT_NRBITS_MSK;
+
+ BUG_ON((this->bbt_options & NAND_BBT_NO_OOB) &&
+ !(this->bbt_options & NAND_BBT_USE_FLASH));
+ BUG_ON(!bits);
+
+ if (bd->options & NAND_BBT_VERSION)
+ pattern_len++;
+
+ if (bd->options & NAND_BBT_NO_OOB) {
+ BUG_ON(!(this->bbt_options & NAND_BBT_USE_FLASH));
+ BUG_ON(!(this->bbt_options & NAND_BBT_NO_OOB));
+ BUG_ON(bd->offs);
+ if (bd->options & NAND_BBT_VERSION)
+ BUG_ON(bd->veroffs != bd->len);
+ BUG_ON(bd->options & NAND_BBT_SAVECONTENT);
+ }
+
+ table_size = mtd->size >> this->block_shift;
+ table_size >>= 3;
+ table_size *= bits;
+ if (bd->options & NAND_BBT_NO_OOB)
+ table_size += pattern_len;
+ BUG_ON(table_size > (1 << this->block_shift));
+}
+
+/**
+ * spi_nand_scan_bbt - [SPI-NAND Interface] scan, find, read and maybe create
+ * bad block table(s)
+ * @mtd: MTD device structure
+ * @bd: descriptor for the good/bad block search pattern
+ *
+ * The function checks, if a bad block table(s) is/are already available. If
+ * not it scans the device for manufacturer marked good / bad blocks and writes
+ * the bad block table(s) to the selected place.
+ *
+ * The bad block table memory is allocated here. It must be freed by calling
+ * the spi_nand_free_bbt function.
+ */
+int spi_nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int len, res = 0;
+ uint8_t *buf;
+ struct nand_bbt_descr *td = this->bbt_td;
+ struct nand_bbt_descr *md = this->bbt_md;
+
+ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__);
+ len = mtd->size >> (this->block_shift + 2);
+ /*
+ * Allocate memory (2bit per block) and clear the memory bad block
+ * table.
+ */
+ this->bbt = kzalloc(len, GFP_KERNEL);
+ if (!this->bbt)
+ return -ENOMEM;
+
+ /*
+ * If no primary table decriptor is given, scan the device to build a
+ * memory based bad block table.
+ */
+ if (!td) {
+ res = spi_nand_memory_bbt(mtd, bd);
+ if (res) {
+ pr_err("spi_nand_bbt: can't scan flash and build the RAM-based BBT\n");
+ kfree(this->bbt);
+ this->bbt = NULL;
+ }
+ return res;
+ }
+ verify_bbt_descr(mtd, td);
+ verify_bbt_descr(mtd, md);
+
+ /* Allocate a temporary buffer for one eraseblock incl. oob */
+ len = (1 << this->block_shift);
+ len += (len >> this->page_shift) * mtd->oobsize;
+ buf = vmalloc(len);
+ if (!buf) {
+ kfree(this->bbt);
+ this->bbt = NULL;
+ return -ENOMEM;
+ }
+
+ /* Is the bbt at a given page? */
+ if (td->options & NAND_BBT_ABSPAGE)
+ read_abs_bbts(mtd, buf, td, md);
+ else {
+ /* Search the bad block table using a pattern in oob */
+ search_read_bbts(mtd, buf, td, md);
+ }
+
+ res = check_create(mtd, buf, bd);
+
+ /* Prevent the bbt regions from erasing / writing */
+ mark_bbt_region(mtd, td);
+ if (md)
+ mark_bbt_region(mtd, md);
+
+ vfree(buf);
+ return res;
+}
+EXPORT_SYMBOL(spi_nand_scan_bbt);
+
+/**
+ * spi_nand_update_bbt - update bad block table(s)
+ * @mtd: MTD device structure
+ * @offs: the offset of the newly marked block
+ *
+ * The function updates the bad block table(s).
+ */
+static int spi_nand_update_bbt(struct mtd_info *mtd, loff_t offs)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int len, res = 0;
+ int chip, chipsel;
+ uint8_t *buf;
+ struct nand_bbt_descr *td = this->bbt_td;
+ struct nand_bbt_descr *md = this->bbt_md;
+
+ if (!this->bbt || !td)
+ return -EINVAL;
+
+ /* Allocate a temporary buffer for one eraseblock incl. oob */
+ len = (1 << this->block_shift);
+ len += (len >> this->page_shift) * mtd->oobsize;
+ buf = kmalloc(len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ chip = 0;
+ chipsel = -1;
+
+ td->version[chip]++;
+ if (md)
+ md->version[chip]++;
+
+ /* Write the bad block table to the device? */
+ if (td->options & NAND_BBT_WRITE) {
+ res = write_bbt(mtd, buf, td, md, chipsel);
+ if (res < 0)
+ goto out;
+ }
+ /* Write the mirror bad block table to the device? */
+ if (md && (md->options & NAND_BBT_WRITE))
+ res = write_bbt(mtd, buf, md, td, chipsel);
+
+out:
+ kfree(buf);
+ return res;
+}
+
+/*
+ * Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks.
+ */
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+/* Generic flash bbt descriptors */
+static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION,
+ .offs = 4, //.offs = 8,
+ .len = 4,
+ .veroffs = 2, //.veroffs = 12,
+ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+ .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION,
+ .offs = 4, //.offs = 8,
+ .len = 4,
+ .veroffs = 2, //.veroffs = 12,
+ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+ .pattern = mirror_pattern
+};
+
+static struct nand_bbt_descr bbt_main_no_oob_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_NO_OOB,
+ .len = 4,
+ .veroffs = 4,
+ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+ .pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_no_oob_descr = {
+ .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+ | NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_NO_OOB,
+ .len = 4,
+ .veroffs = 4,
+ .maxblocks = NAND_BBT_SCAN_MAXBLOCKS,
+ .pattern = mirror_pattern
+};
+
+#define BADBLOCK_SCAN_MASK (~NAND_BBT_NO_OOB)
+/**
+ * spi_nand_create_badblock_pattern - [INTERN] Creates a BBT descriptor structure
+ * @this: SPI-NAND chip to create descriptor for
+ *
+ * This function allocates and initializes a nand_bbt_descr for BBM detection
+ * based on the properties of @this. The new descriptor is stored in
+ * this->badblock_pattern. Thus, this->badblock_pattern should be NULL when
+ * passed to this function.
+ */
+static int spi_nand_create_badblock_pattern(struct spi_nand_chip *this)
+{
+ struct nand_bbt_descr *bd;
+
+ if (this->badblock_pattern) {
+ pr_warn("Bad block pattern already allocated; not replacing\n");
+ return -EINVAL;
+ }
+ bd = kzalloc(sizeof(*bd), GFP_KERNEL);
+ if (!bd)
+ return -ENOMEM;
+ bd->options = this->bbt_options & BADBLOCK_SCAN_MASK;
+ bd->offs = this->badblockpos;
+ bd->len = 1;
+ bd->pattern = scan_ff_pattern;
+ bd->options |= NAND_BBT_DYNAMICSTRUCT;
+ this->badblock_pattern = bd;
+ return 0;
+}
+
+/**
+ * spi_nand_default_bbt - [SPI-NAND Interface] Select a default bad block table for the device
+ * @mtd: MTD device structure
+ *
+ * This function selects the default bad block table support for the device and
+ * calls the spi_nand_scan_bbt function.
+ */
+int spi_nand_default_bbt(struct mtd_info *mtd)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int ret;
+
+ fh_dev_debug(&this->spi->dev, "Enter %s\n", __func__);
+
+ fh_dev_debug(&this->spi->dev, "\tbbt option %x\n", this->bbt_options);
+ /* Is a flash based bad block table requested? */
+ if (this->bbt_options & NAND_BBT_USE_FLASH) {
+ /* Use the default pattern descriptors */
+ if (!this->bbt_td) {
+ if (this->bbt_options & NAND_BBT_NO_OOB) {
+ this->bbt_td = &bbt_main_no_oob_descr;
+ this->bbt_md = &bbt_mirror_no_oob_descr;
+ } else {
+ this->bbt_td = &bbt_main_descr;
+ this->bbt_md = &bbt_mirror_descr;
+ }
+ }
+ } else {
+ this->bbt_td = NULL;
+ this->bbt_md = NULL;
+ }
+
+ if (!this->badblock_pattern) {
+ ret = spi_nand_create_badblock_pattern(this);
+ if (ret)
+ return ret;
+ }
+
+ fh_dev_debug(&this->spi->dev, "badblock pattern 0x%02x\n",
+ * this->badblock_pattern->pattern);
+ return spi_nand_scan_bbt(mtd, this->badblock_pattern);
+}
+EXPORT_SYMBOL(spi_nand_default_bbt);
+
+/**
+ * spi_nand_isbad_bbt - [SPI-NAND Interface] Check if a block is bad
+ * @mtd: MTD device structure
+ * @offs: offset in the device
+ * @allowbbt: allow access to bad block table region
+ */
+int spi_nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int block, res;
+
+ block = (int)(offs >> this->block_shift);
+ res = bbt_get_entry(this, block);
+
+ pr_debug("%s: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+ __func__, (unsigned int)offs, block, res);
+
+ switch (res) {
+ case BBT_BLOCK_GOOD:
+ return 0;
+ case BBT_BLOCK_WORN:
+ return 1;
+ case BBT_BLOCK_RESERVED:
+ return allowbbt ? 0 : 1;
+ }
+ return 1;
+}
+EXPORT_SYMBOL(spi_nand_isbad_bbt);
+/**
+ * spi_nand_markbad_bbt - [SPI-NAND Interface] Mark a block bad in the BBT
+ * @mtd: MTD device structure
+ * @offs: offset of the bad block
+ */
+int spi_nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
+{
+ struct spi_nand_chip *this = mtd->priv;
+ int block, ret = 0;
+
+ block = (int)(offs >> this->block_shift);
+
+ /* Mark bad block in memory */
+ bbt_mark_entry(this, block, BBT_BLOCK_WORN);
+
+ /* Update flash-based bad block table */
+ if (this->bbt_options & NAND_BBT_USE_FLASH)
+ ret = spi_nand_update_bbt(mtd, offs);
+
+ return ret;
+}
+EXPORT_SYMBOL(spi_nand_markbad_bbt);
diff --git a/drivers/mtd/spi-nand/spi-nand-device.c b/drivers/mtd/spi-nand/spi-nand-device.c
new file mode 100644
index 00000000..c2ce188a
--- /dev/null
+++ b/drivers/mtd/spi-nand/spi-nand-device.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2009-2014 Micron Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/mtd/spi-nand.h>
+#include "spi-nand-ids.h"
+
+#ifdef SPINAND_BBT_DEBUG
+#define fh_dev_debug dev_err
+#else
+#define fh_dev_debug(...)
+#endif
+
+#define ONE_WIRE_SUPPORT (1<<0)
+#define DUAL_WIRE_SUPPORT (1<<1)
+#define QUAD_WIRE_SUPPORT (1<<2)
+#define MULTI_WIRE_SUPPORT (1<<8)
+
+static int spi_nand_read_id(struct spi_nand_chip *chip, u8 *buf)
+{
+ struct spi_device *spi = chip->spi;
+ struct spi_nand_cmd cmd = { 0 };
+
+ cmd.cmd = SPINAND_CMD_READ_ID;
+
+ if (chip->read_id_dummy != SPI_NAND_ID_NO_DUMMY) {
+ cmd.n_addr = 1;
+ cmd.addr[0] = 0x00;
+ }
+
+ cmd.n_rx = SPINAND_MAX_ID_LEN;
+ cmd.rx_buf = buf;
+
+ return spi_nand_send_cmd(spi, &cmd);
+}
+
+static void spi_nand_ecc_status(struct spi_nand_chip *chip, unsigned int status,
+ unsigned int *corrected, unsigned int *ecc_error)
+{
+ unsigned int ecc_status = (status >> SPI_NAND_ECC_SHIFT) &
+ chip->ecc_mask;
+
+ *ecc_error = (ecc_status == chip->ecc_uncorr);
+ if (*ecc_error == 0)
+ *corrected = ecc_status;
+}
+
+/*static int spi_nand_manufacture_init(struct spi_nand_chip *chip)
+{
+ switch (chip->mfr_id) {
+ case SPINAND_MFR_MICRON:
+ chip->get_ecc_status = spi_nand_mt29f_ecc_status;
+
+ if (chip->page_spare_size == 64)
+ chip->ecclayout = &micron_ecc_layout_64;
+
+ chip->bbt_options |= NAND_BBT_NO_OOB;
+ break;
+ case SPINAND_MFR_GIGADEVICE:
+ chip->get_ecc_status = spi_nand_gd5f_ecc_status;
+ chip->read_cache = spi_nand_read_from_cache_snor_protocol;
+ chip->ecc_strength_ds = 8;
+ chip->ecc_step_ds = chip->page_size >> 2;
+ if (chip->page_spare_size == 128)
+ chip->ecclayout = &gd5f_ecc_layout_128;
+ else if (chip->page_spare_size == 256)
+ chip->ecclayout = &gd5f_ecc_layout_256;
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}*/
+
+static int spi_nand_device_probe(struct spi_device *spi)
+{
+ struct spi_nand_chip *chip;
+ struct mtd_info *mtd;
+ /* struct mtd_part_parser_data ppdata;*/
+ int ret;
+ struct flash_platform_data *data;
+
+ fh_dev_debug(&spi->dev, "%s with spi%d:%d \n", __func__,
+ spi->master->bus_num, spi->chip_select);
+
+ data = dev_get_platdata(&spi->dev);
+ chip = kzalloc(sizeof(struct spi_nand_chip), GFP_KERNEL);
+ if (!chip) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+ chip->spi = spi;
+
+ mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+ if (!mtd) {
+ ret = -ENOMEM;
+ goto err2;
+ }
+ mtd->priv = chip;
+ chip->mtd = mtd;
+ dev_set_drvdata(&spi->dev, chip);
+ /*spi_set_drvdata(spi, chip);*/
+ mtd->dev.parent = &spi->dev;
+ chip->read_id = spi_nand_read_id;
+ ret = spi_nand_scan_ident(mtd);
+ if (ret) {
+ ret = -ENODEV;
+ goto err3;
+ }
+
+/* spi_nand_manufacture_init(chip);*/
+ chip->get_ecc_status = spi_nand_ecc_status;
+ mtd->dev.of_node = spi->dev.of_node;
+ mtd->name = dev_name(mtd->dev.parent);
+ ret = spi_nand_scan_tail(mtd);
+ if (ret) {
+ fh_dev_debug(&spi->dev, "goto err4 %s\n", __func__);
+ goto err4;
+ }
+
+ fh_dev_debug(&spi->dev, " mtd_device_register %s\n", __func__);
+ ret = mtd_device_register(mtd, data ? data->parts : NULL,
+ data ? data->nr_parts : 0);
+ if (!ret)
+ return 0;
+ fh_dev_debug(&spi->dev, " spi_nand_scan_tail_release %s\n", __func__);
+ spi_nand_scan_tail_release(mtd);
+ fh_dev_debug(&spi->dev, "Leave %s\n", __func__);
+err4:
+ spi_nand_scan_ident_release(mtd);
+err3:
+ kfree(mtd);
+err2:
+ kfree(chip);
+err1:
+ return ret;
+}
+
+int spi_nand_device_remove(struct spi_device *spi)
+{
+ struct spi_nand_chip *chip = spi_get_drvdata(spi);
+ struct mtd_info *mtd = chip->mtd;
+
+ spi_nand_release(mtd);
+ kfree(mtd);
+ kfree(chip);
+
+ return 0;
+}
+void spi_nand_shutdown(struct spi_device *spi)
+{
+ struct spi_nand_cmd cmd = {0};
+
+ /* before reset delay 1ms */
+ udelay(1000);
+ cmd.cmd = SPINAND_CMD_RESET;
+ if (spi_nand_send_cmd(spi, &cmd) < 0)
+ pr_err("spi_nand reset failed!\n");
+
+ /* elapse 1ms before issuing any other command */
+ udelay(1000);
+
+}
+
+
+static const struct of_device_id spinand_dt[] = {
+ { .compatible = "fh spi-nand", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, spinand_dt);
+
+/*
+ * Device name structure description
+ */
+static struct spi_driver spinand_driver = {
+ .driver = {
+ .name = "spi-nand",
+ .of_match_table = spinand_dt,
+ },
+ .probe = spi_nand_device_probe,
+ .remove = spi_nand_device_remove,
+ .shutdown = spi_nand_shutdown,
+};
+
+module_spi_driver(spinand_driver);
+
+MODULE_DESCRIPTION("Fullhan SPI NAND device driver");
+MODULE_AUTHOR("Peter Pan<peterpandong at micron.com>");
+MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia at imgtec.com>");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/mtd/spi-nand/spi-nand-ids.c b/drivers/mtd/spi-nand/spi-nand-ids.c
new file mode 100644
index 00000000..d6a86cf3
--- /dev/null
+++ b/drivers/mtd/spi-nand/spi-nand-ids.c
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2016 Fullhan, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/spi-nand.h>
+#include <linux/mtd/bbm.h>
+
+/*static struct spi_nand_flash spi_nand_table[] = {
+ SPI_NAND_INFO("MT29F2G01AAAED", 0x2C, 0X22, 2048, 64, 64, 2048,
+ SPINAND_NEED_PLANE_SELECT),
+ SPI_NAND_INFO("MT29F4G01AAADD", 0x2C, 0X32, 2048, 64, 64, 4096,
+ SPINAND_NEED_PLANE_SELECT),
+ SPI_NAND_INFO("GD5F 512MiB 1.8V", 0xC8, 0XA4, 4096, 256, 64, 2048,
+ 0),
+ SPI_NAND_INFO("GD5F 512MiB 3.3V", 0xC8, 0XB4, 4096, 256, 64, 2048,
+ 0),
+ SPI_NAND_INFO("GD5F 256MiB 3.3V", 0xC8, 0XB2, 2048, 128, 64, 2048,
+ 0),
+ SPI_NAND_INFO("GD5F 128MiB 3.3V", 0xC8, 0XB1, 2048, 128, 64, 1024,
+ 0),
+ SPI_NAND_INFO("W25N01GV", 0xEF, 0XAA21, 2048, 64, 64, 1024,
+ 0),
+ {.name = NULL},
+};*/
+
+/**
+* Default OOB area specification layout
+*/
+static struct nand_ecclayout ecc_layout_64 = {
+ .eccbytes = 32,
+ .eccpos = {
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 24, 25, 26, 27, 28, 29, 30, 21,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 56, 57, 58, 59, 60, 61, 62, 63
+ },
+ .oobavail = 30,
+ .oobfree = {
+ {
+ .offset = 2,
+ .length = 6
+ }, {
+ .offset = 16,
+ .length = 8
+ }, {
+ .offset = 32,
+ .length = 8
+ }, {
+ .offset = 48,
+ .length = 8
+ },
+ }
+};
+
+static struct nand_ecclayout gd5f_ecc_layout_256 = {
+ .eccbytes = 128,
+ .eccpos = {
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255
+ },
+ .oobavail = 127,
+ .oobfree = { {1, 127} }
+};
+
+static struct nand_ecclayout gd5f_ecc_layout_128 = {
+ .eccbytes = 64,
+ .eccpos = {
+ 64, 65, 66, 67, 68, 69, 70, 72,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ },
+ .oobavail = 62,
+ .oobfree = { {2, 63} }
+};
+
+static struct nand_ecclayout pn26_ecc_layout_128 = {
+ .eccbytes = 52,
+ .eccpos = {
+ 6, 7, 8, 9, 10, 11, 12, 13, 14,15,16,17,18,
+ 21,22,23,24,25,26,27,28,29,30,31,32,33,
+ 36,37,38,39,40,41,42,43,44,45,46,47,48,
+ 51,52,53,54,55,56,57,58,59,60,61,62,63
+ },
+ .oobavail = 72,
+ .oobfree = {
+ {
+ .offset = 4,
+ .length = 2
+ }, {
+ .offset = 19,
+ .length = 2
+ }, {
+ .offset = 34,
+ .length = 2
+ }, {
+ .offset = 49,
+ .length = 2
+ },
+ {
+ .offset = 64,
+ .length = 64
+ },
+ }
+};
+
+static struct nand_ecclayout default_ecc_layout = {
+ .eccbytes = 64,
+ .oobavail = 28,
+ .oobfree = { { 2, 30 } }
+};
+
+static struct nand_ecclayout mx35_ecc_layout_64 = {
+ .eccbytes = 0,
+ .oobavail = 62,
+ .oobfree = { {2, 62} }
+};
+
+static struct nand_ecclayout mt29f_ecc_layout_128 = {
+ .eccbytes = 64,
+ .oobavail = 60,
+ .oobfree = { {4, 60} }
+};
+static struct nand_ecclayout tc58_ecc_layout_64 = {
+ .eccbytes = 0,
+ .oobavail = 60,
+ .oobfree = { {4, 60} }
+};
+
+static struct nand_ecclayout ds35_ecc_layout_64 = {
+ .eccbytes = 16,
+ .oobavail = 32,
+ .oobfree = {
+ {
+ .offset = 8,
+ .length = 8
+ }, {
+ .offset = 24,
+ .length = 8
+ }, {
+ .offset = 40,
+ .length = 8
+ }, {
+ .offset = 56,
+ .length = 8
+ },
+ }
+};
+
+static struct nand_ecclayout fs35_ecc_layout_64 = {
+ .eccbytes = 0,
+ .oobavail = 62,
+ .oobfree = { {2, 62} }
+};
+
+static struct nand_ecclayout xt_ecc_layout_128 = {
+ .eccbytes = 52,
+ .eccpos = {
+ 64, 65, 66, 67, 68, 69, 70, 72,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115,
+ },
+ .oobavail = 74,
+ .oobfree = { {2, 62}, {116, 12} }
+};
+
+static struct nand_ecclayout en_ecc_layout_64 = {
+ .eccbytes = 52,
+ .eccpos = {
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63,
+ },
+ .oobavail = 10,
+ .oobfree = {
+ {
+ .offset = 2,
+ .length = 1
+ }, {
+ .offset = 16,
+ .length = 3
+ }, {
+ .offset = 32,
+ .length = 3
+ }, {
+ .offset = 48,
+ .length = 3
+ },
+ }
+};
+
+static struct spi_nand_flash spi_nand_table[] = {
+ {
+ .name = "W25N01GV",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 3,
+ },
+ .dev_id = {0xEF, 0xAA, 0x21},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &ecc_layout_64,
+ .qe_addr = 0xa0,
+ .qe_flag = 0x0,
+ .qe_mask = 1<<1,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "MX35LF1GE4AB",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0xC2, 0x12},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &mx35_ecc_layout_64,
+ .qe_addr = 0xb0,
+ .qe_flag = 0x1,
+ .qe_mask = 1<<0,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "MX35LF2GE4AB",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0xC2, 0x22},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 2048,
+ .options = SPINAND_NEED_PLANE_SELECT,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &mx35_ecc_layout_64,
+ .qe_addr = 0xb0,
+ .qe_flag = 0x1,
+ .qe_mask = 1<<0,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "GD5F1GQ4UC",
+ .id_info = {
+ .id_addr = SPI_NAND_ID_NO_DUMMY,
+ .id_len = 3,
+ },
+ .dev_id = {0xC8, 0xB1, 0x48},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = FIRST_DUMMY_BYTE,
+ .ecc_mask = 7,
+ .ecc_uncorr = 7,
+ .ecc_layout = &gd5f_ecc_layout_128,
+ .qe_addr = 0xb0,
+ .qe_flag = 0x1,
+ .qe_mask = 1<<0,
+ .multi_wire_command_length = 5,
+ },
+ {
+ .name = "GD5F2GQ4UC",
+ .id_info = {
+ .id_addr = SPI_NAND_ID_NO_DUMMY,
+ .id_len = 3,
+ },
+ .dev_id = {0xC8, 0xB2, 0x48},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = FIRST_DUMMY_BYTE,
+ .ecc_mask = 7,
+ .ecc_uncorr = 7,
+ .ecc_layout = &gd5f_ecc_layout_128,
+ .qe_addr = 0xb0,
+ .qe_flag = 0x1,
+ .qe_mask = 1<<0,
+ .multi_wire_command_length = 5,
+ },
+ {
+ .name = "GD5F2GQ4UB",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0xC8, 0xD2},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 2048,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &gd5f_ecc_layout_128,
+ .qe_addr = 0xb0,
+ .qe_flag = 0x1,
+ .qe_mask = 1<<0,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "GD5F1GQ4UB",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0xC8, 0xD1},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &gd5f_ecc_layout_128,
+ .qe_addr = 0xb0,
+ .qe_flag = 0x1,
+ .qe_mask = 1<<0,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "PN26G01A",
+ .id_info = {
+ .id_addr = 0x0,
+ .id_len = 2,
+ },
+ .dev_id = {0xA1, 0xE1},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &pn26_ecc_layout_128,
+ .qe_addr = 0xb0,
+ .qe_flag = 0x1,
+ .qe_mask = 1<<0,
+ .multi_wire_command_length = 4,
+ },
+ /*MT29F1G01*/
+ {
+ .name = "MT29F1G01",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0x2c, 0x14},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &mt29f_ecc_layout_128,
+ .qe_addr = 0xa0,
+ .qe_mask = 1<<1,
+ .qe_flag = 0,
+ .multi_wire_command_length = 4,
+ },
+ /*TC58CVG0S3H*/
+ {
+ .name = "TC58CVG0S3H",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0x98, 0xc2},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &tc58_ecc_layout_64,
+ .qe_addr = 0xa0,
+ .qe_mask = 1<<1,
+ .qe_flag = 0,
+ .multi_wire_command_length = 4,
+ },
+ /*DS35X1GA*/
+ {
+ .name = "DS35X1GA",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0xe5, 0x71},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &ds35_ecc_layout_64,
+ .qe_addr = 0xb0,
+ .qe_mask = 1<<0,
+ .qe_flag = 1,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "FS35ND01G-S1Y2",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 3,
+ },
+ .dev_id = {0xcd, 0xea, 0x11},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &fs35_ecc_layout_64,
+ .qe_addr = 0xb0,
+ .qe_mask = 1<<0,
+ .qe_flag = 1,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "TC58CVGS3HRAIJ",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 3,
+ },
+ .dev_id = {0x98, 0xe2, 0x40},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &fs35_ecc_layout_64,
+ .multi_wire_command_length = 4,
+ .bitflip_threshold = 3,
+ },
+ {
+ .name = "FM25S01A",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0xa1, 0xe4},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &fs35_ecc_layout_64,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "XT26G11C",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0x0b, 0x15},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &xt_ecc_layout_128,
+ .qe_addr = 0xb0,
+ .qe_mask = 1<<0,
+ .qe_flag = 1,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "FS35SQA001G",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 3,
+ },
+ .dev_id = {0xcd, 0x71, 0x71},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &fs35_ecc_layout_64,
+ .qe_addr = 0xb0,
+ .qe_mask = 1<<0,
+ .qe_flag = 1,
+ .multi_wire_command_length = 4,
+ },
+ {
+ .name = "ENADSW1G",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0x2c, 0xc1},
+ .page_size = 2048,
+ .page_spare_size = 64,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 3,
+ .ecc_uncorr = 2,
+ .ecc_layout = &en_ecc_layout_64,
+ .qe_addr = 0xb0,
+ .qe_mask = 1<<0,
+ .qe_flag = 1,
+ .multi_wire_command_length = 4,
+ .bbt_options = NAND_BBT_NO_OOB,
+ },
+ {
+ .name = "XT26G01C",
+ .id_info = {
+ .id_addr = 0,
+ .id_len = 2,
+ },
+ .dev_id = {0x0b, 0x11},
+ .page_size = 2048,
+ .page_spare_size = 128,
+ .pages_per_blk = 64,
+ .blks_per_chip = 1024,
+ .options = 0,
+ .ecc_mask = 15,
+ .ecc_uncorr = 15,
+ .ecc_layout = &xt_ecc_layout_128,
+ .qe_addr = 0xb0,
+ .qe_mask = 1<<0,
+ .qe_flag = 1,
+ .multi_wire_command_length = 4,
+ .bitflip_threshold = 4,
+ },
+};
+
+/**
+ * spi_nand_scan_id_table - [INTERN] scan chip info in id table
+ * @chip: SPI-NAND device structure
+ * @id: point to manufacture id and device id
+ */
+bool spi_nand_scan_id_table(struct spi_nand_chip *chip, u8 *id)
+{
+ int i, j = 0;
+ struct spi_nand_flash *type = spi_nand_table;
+ int m=0;
+
+ for (m=0; m<ARRAY_SIZE(spi_nand_table); m++,type++) {
+// if (id[0] == type->mfr_id && id[1] == type->dev_id) {
+ for (j=0, i = 0; j < type->id_info.id_len;j++,i++ ) {
+ if (id[i] != type->dev_id[j])
+ break;
+ }
+ if (j == type->id_info.id_len) {
+ chip->name = type->name;
+ chip->size = type->page_size * type->pages_per_blk
+ * type->blks_per_chip;
+ chip->block_size = type->page_size
+ * type->pages_per_blk;
+ chip->page_size = type->page_size;
+ chip->page_spare_size = type->page_spare_size;
+ chip->block_shift = ilog2(chip->block_size);
+ chip->page_shift = ilog2(chip->page_size);
+ chip->page_mask = chip->page_size - 1;
+ chip->options = type->options;
+ if (!type->ecc_layout)
+ chip->ecclayout = &default_ecc_layout;
+ else
+ chip->ecclayout = type->ecc_layout;
+ chip->dev_id_len = type->id_info.id_len;
+ chip->ecc_uncorr = type->ecc_uncorr;
+ chip->ecc_mask = type->ecc_mask;
+ memcpy(chip->dev_id, type->dev_id, chip->dev_id_len);
+ chip->qe_addr = type->qe_addr;
+ chip->qe_flag = type->qe_flag;
+ chip->qe_mask = type->qe_mask;
+ chip->multi_wire_command_length =
+ type->multi_wire_command_length;
+ chip->bbt_options = type->bbt_options;
+ chip->bitflip_threshold = type->bitflip_threshold;
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/drivers/mtd/spi-nand/spi-nand-ids.h b/drivers/mtd/spi-nand/spi-nand-ids.h
new file mode 100644
index 00000000..c488eee5
--- /dev/null
+++ b/drivers/mtd/spi-nand/spi-nand-ids.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 Fullhan, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef DRIVERS_MTD_SPI_NAND_SPI_NAND_IDS_H_
+#define DRIVERS_MTD_SPI_NAND_SPI_NAND_IDS_H_
+
+enum spi_nand_device_variant {
+ SPI_NAND_GENERIC,
+ SPI_NAND_MT29F,
+ SPI_NAND_GD5F,
+};
+
+
+bool spi_nand_scan_id_table(struct spi_nand_chip *chip, u8 *id);
+
+#endif /* DRIVERS_MTD_SPI_NAND_SPI_NAND_IDS_H_ */
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 21dde524..07c19e67 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -37,47 +37,12 @@
*/
#define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ)
-#define SPI_NOR_MAX_ID_LEN 6
-#define SPI_NOR_MAX_ADDR_WIDTH 4
-struct flash_info {
- char *name;
-
- /*
- * This array stores the ID bytes.
- * The first three bytes are the JEDIC ID.
- * JEDEC ID zero means "no ID" (mostly older chips).
- */
- u8 id[SPI_NOR_MAX_ID_LEN];
- u8 id_len;
+#define JEDEC_MFR(info) ((info)->id[0])
- /* The size listed here is what works with SPINOR_OP_SE, which isn't
- * necessarily called a "sector" by the vendor.
- */
- unsigned sector_size;
- u16 n_sectors;
-
- u16 page_size;
- u16 addr_width;
-
- u16 flags;
-#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */
-#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */
-#define SST_WRITE BIT(2) /* use SST byte programming */
-#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */
-#define SECT_4K_PMC BIT(4) /* SPINOR_OP_BE_4K_PMC works uniformly */
-#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */
-#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */
-#define USE_FSR BIT(7) /* use flag status register */
-#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */
-#define SPI_NOR_HAS_TB BIT(9) /*
- * Flash SR has Top/Bottom (TB) protect
- * bit. Must be used with
- * SPI_NOR_HAS_LOCK.
- */
-};
+#define JEDEC_MEMTYPE(info) ((info)->id[1])
-#define JEDEC_MFR(info) ((info)->id[0])
+#define FLASH_DEFAULT_CLOCK_FREQ (50000000)
static const struct flash_info *spi_nor_match_id(const char *name);
@@ -220,6 +185,7 @@ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
static inline int spi_nor_sr_ready(struct spi_nor *nor)
{
int sr = read_sr(nor);
+
if (sr < 0)
return sr;
else
@@ -229,6 +195,7 @@ static inline int spi_nor_sr_ready(struct spi_nor *nor)
static inline int spi_nor_fsr_ready(struct spi_nor *nor)
{
int fsr = read_fsr(nor);
+
if (fsr < 0)
return fsr;
else
@@ -238,6 +205,7 @@ static inline int spi_nor_fsr_ready(struct spi_nor *nor)
static int spi_nor_ready(struct spi_nor *nor)
{
int sr, fsr;
+
sr = spi_nor_sr_ready(nor);
if (sr < 0)
return sr;
@@ -746,7 +714,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
}
/* Used when the "_ext_id" is two bytes at most */
-#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags, _speed) \
.id = { \
((_jedec_id) >> 16) & 0xff, \
((_jedec_id) >> 8) & 0xff, \
@@ -758,9 +726,10 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
.sector_size = (_sector_size), \
.n_sectors = (_n_sectors), \
.page_size = 256, \
- .flags = (_flags),
+ .flags = (_flags), \
+ .max_speed_hz = (_speed),
-#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
+#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags, _speed) \
.id = { \
((_jedec_id) >> 16) & 0xff, \
((_jedec_id) >> 8) & 0xff, \
@@ -773,14 +742,17 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
.sector_size = (_sector_size), \
.n_sectors = (_n_sectors), \
.page_size = 256, \
- .flags = (_flags),
+ .flags = (_flags), \
+ .max_speed_hz = (_speed),
-#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \
+
+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags, _speed) \
.sector_size = (_sector_size), \
.n_sectors = (_n_sectors), \
.page_size = (_page_size), \
.addr_width = (_addr_width), \
- .flags = (_flags),
+ .flags = (_flags), \
+ .max_speed_hz = (_speed),
/* NOTE: double check command sets and memory organization when you add
* more nor chips. This current list focusses on newer chips, which
@@ -795,223 +767,422 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
*/
static const struct flash_info spi_nor_ids[] = {
/* Atmel -- some are (confusingly) marketed as "DataFlash" */
- { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) },
- { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
-
- { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
- { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
- { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
-
- { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
- { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
- { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
- { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
-
- { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
+ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+
+ { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+
+ { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+
+ { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
/* EON -- en25xxx */
- { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
- { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
- { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
- { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
- { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
- { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
- { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
- { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25qh64a", INFO(0x1c7017, 0, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25qh128a", INFO(0x1c7018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
/* ESMT */
- { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) },
+ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
/* Everspin */
- { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-
+ { "mr25h256", CAT25_INFO(32 * 1024, 1, 256, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, FLASH_DEFAULT_CLOCK_FREQ) },
/* Fujitsu */
- { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
-
+ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1,
+ SPI_NOR_NO_ERASE, FLASH_DEFAULT_CLOCK_FREQ) },
/* GigaDevice */
- {
- "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ)
},
+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ)},
+
+ { "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
/* Intel/Numonyx -- xxxs33b */
- { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
- { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
- { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
/* ISSI */
- { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) },
+ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
/* Macronix */
- { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) },
- { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
- { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
- { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
- { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
- { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
- { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
- { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
- { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
- { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
- { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
- { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
+ { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024,
+ SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048,
+ SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
/* Micron */
- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048,
+ SECT_4K | USE_FSR | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
/* PMC */
- { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
- { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
- { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2,
+ SECT_4K_PMC, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4,
+ SECT_4K_PMC, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+ { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
- { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
- { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
- { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
- { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
- { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
- { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
- { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
- { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
- { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
- { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
- { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) },
+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8,
+ SECT_4K | SPI_NOR_DUAL_READ, FLASH_DEFAULT_CLOCK_FREQ) },
/* SST -- large erase sizes are "overlays", "sectors" are 4K */
- { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
- { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
- { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) },
- { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) },
- { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) },
- { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) },
- { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) },
- { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) },
- { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) },
- { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
- { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
- { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
+ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16,
+ SECT_4K | SST_WRITE, FLASH_DEFAULT_CLOCK_FREQ) },
/* ST Microelectronics -- newer production may have feature updates */
- { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
- { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) },
- { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) },
- { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) },
- { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) },
- { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) },
- { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
- { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
- { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
-
- { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
- { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
- { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) },
- { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) },
- { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) },
- { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) },
- { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) },
- { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) },
- { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) },
-
- { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) },
- { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) },
- { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) },
-
- { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) },
- { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) },
- { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) },
-
- { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) },
- { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) },
- { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) },
-
- /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
- { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
- { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
- { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
- { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
- { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
- { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
- { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
- {
- "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
- { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- {
- "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
+ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p10", INFO(0x202011, 0, 32 * 1024, 4,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p20", INFO(0x202012, 0, 64 * 1024, 4,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p40", INFO(0x202013, 0, 64 * 1024, 8,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p80", INFO(0x202014, 0, 64 * 1024, 16,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p16", INFO(0x202015, 0, 64 * 1024, 32,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+
+ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+
+ { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+
+ { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+
+ { "m25px16", INFO(0x207115, 0, 64 * 1024, 32,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25px32", INFO(0x207116, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64,
+ SECT_4K, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25px64", INFO(0x207117, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "m25px80", INFO(0x207114, 0, 64 * 1024, 16,
+ 0, FLASH_DEFAULT_CLOCK_FREQ) },
/* Catalyst / On Semiconductor -- non-JEDEC */
- { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c11", CAT25_INFO(16, 8, 16, 1,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "cat25c03", CAT25_INFO(32, 8, 16, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "cat25c09", CAT25_INFO(128, 8, 32, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "cat25c17", CAT25_INFO(256, 8, 32, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "cat25128", CAT25_INFO(2048, 8, 64, 2,
+ SPI_NOR_NO_ERASE | SPI_NOR_NO_FR, FLASH_DEFAULT_CLOCK_FREQ) },
+ { "xm25qh128a", INFO(0x207018, 0, 64 * 1024, 256,
+ 0, FLASH_DEFAULT_CLOCK_FREQ)},
+ { "xm25qh64a", INFO(0x207017, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ)},
+ { "xm25qh128b", INFO(0x206018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
+ { "xm25qh64b", INFO(0x206017, 0, 64 * 1024, 128,
+ 0, FLASH_DEFAULT_CLOCK_FREQ)},
+ { "xm25qh128c", INFO(0x204018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
+ { "xm25qh64c", INFO(0x204017, 0, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
+ { "nm25q128evb", INFO(0x522118, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
+ { "fm25q128a", INFO(0xa14018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
+ { "xt25f128b", INFO(0x0b4018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
+ { "zb25vq128a", INFO(0x5e4018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
+ { "by25q128as", INFO(0x684018, 0, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
+ FLASH_DEFAULT_CLOCK_FREQ)},
{ },
};
+static void spi_nor_scan_delay(struct spi_nor *nor, const struct flash_info *info)
+{
+ int tmp;
+ int count;
+ u8 id[SPI_NOR_MAX_ID_LEN];
+
+ count = 5;
+ do {
+ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
+ if (tmp < 0) {
+ dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp);
+ return;
+ }
+
+ if (!memcmp(info->id, id, info->id_len))
+ return;
+
+ nor->scan_delay(nor);
+ } while (count--);
+}
+
static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
{
int tmp;
@@ -1172,9 +1343,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
ssize_t written;
page_offset = (to + i) & (nor->page_size - 1);
- WARN_ONCE(page_offset,
- "Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
- page_offset);
/* the size of data remaining on the first page */
page_remain = min_t(size_t,
nor->page_size - page_offset, len - i);
@@ -1241,6 +1409,101 @@ static int write_sr_cr(struct spi_nor *nor, u16 val)
return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2);
}
+static int xmcb_quad_enable(struct spi_nor *nor)
+{
+ int status;
+ int ret;
+ int quad_en = 1 << 6;
+ /* read back status */
+ status = read_sr(nor);
+ /* qe already enable */
+ if (status & quad_en)
+ return 0;
+
+ nor->cmd_buf[0] = status | quad_en;
+ write_enable(nor);
+ nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret) {
+ dev_err(nor->dev,
+ "timeout while writing configuration register\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int gd_quad_enable(struct spi_nor *nor)
+{
+ int ret;
+ int quad_en = 1 << 1;
+ /* read back status */
+ ret = read_cr(nor);
+ ret |= quad_en;
+ nor->cmd_buf[0] = ret;
+ write_enable(nor);
+ nor->write_reg(nor, SPINOR_OP_GD_WR2, nor->cmd_buf, 1);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret) {
+ dev_err(nor->dev,
+ "timeout while writing configuration register\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int nm_quad_enable(struct spi_nor *nor)
+{
+ int ret;
+ int quad_en = 1 << 2;
+ /* read back status */
+ ret = read_cr(nor);
+ ret |= quad_en;
+ nor->cmd_buf[0] = ret;
+ write_enable(nor);
+ nor->write_reg(nor, SPINOR_OP_GD_WR2, nor->cmd_buf, 1);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret) {
+ dev_err(nor->dev,
+ "timeout while writing configuration register\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int winbond_quad_enable(struct spi_nor *nor)
+{
+ int ret;
+ u8 status_0, status_1;
+ int quad_en = 1 << 1;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &status_0, 1);
+ if (ret < 0) {
+ pr_err("error %d reading SR\n", (int) ret);
+ return ret;
+ }
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDCR, &status_1, 1);
+ if (ret < 0) {
+ pr_err("error %d reading SR\n", (int) ret);
+ return ret;
+ }
+ status_1 &= ~(1 << 1);
+ status_1 |= quad_en;
+ nor->cmd_buf[0] = status_0;
+ nor->cmd_buf[1] = status_1;
+ write_enable(nor);
+ nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret) {
+ dev_err(nor->dev,
+ "timeout while writing configuration register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+
static int spansion_quad_enable(struct spi_nor *nor)
{
int ret;
@@ -1284,8 +1547,50 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
return -EINVAL;
}
return status;
- case SNOR_MFR_MICRON:
- return 0;
+ /* case SNOR_MFR_MICRON->same switch-case */
+ case SNOR_MFR_XMC:
+ /* Specific Operation for Xmc-B serial */
+ if (JEDEC_MEMTYPE(info) == 0x60) {
+ status = xmcb_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "XMCB quad-read not enabled\n");
+ return -EINVAL;
+ }
+ } else
+ status = 0;
+ return status;
+ case SNOR_MFR_WINBOND:
+ case SNOR_MFR_XTX:
+ status = winbond_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "%s quad-read not enabled\n",
+ (JEDEC_MFR(info) == SNOR_MFR_FM) ? "XTX" : "WB");
+ return -EINVAL;
+ }
+ return status;
+ case SNOR_MFR_NM:
+ status = nm_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "NM quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
+ case SNOR_MFR_GIGADEVICE:
+ case SNOR_MFR_FM:
+ case SNOR_MFR_ZB:
+ case SNOR_MFR_BY:
+ status = gd_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "%s quad-read not enabled\n",
+ (JEDEC_MFR(info) == SNOR_MFR_FM) ? "FM" :
+ ((JEDEC_MFR(info) == SNOR_MFR_ZB) ? "ZB" :
+ ((JEDEC_MFR(info) == SNOR_MFR_BY) ? "BY" : "GD")));
+ return -EINVAL;
+ }
+ return status;
+ case SNOR_MFR_EON:
+ status = 0;
+ return status;
default:
status = spansion_quad_enable(nor);
if (status) {
@@ -1327,7 +1632,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
info = spi_nor_read_id(nor);
if (IS_ERR_OR_NULL(info))
return -ENOENT;
-
+ /* bind the flash info */
+ nor->info = (struct flash_info *)info;
/*
* If caller has specified name of flash model that can normally be
* detected using JEDEC, let's verify it.
@@ -1347,8 +1653,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
* information, even if it's not 100% accurate.
*/
dev_warn(dev, "found %s, expected %s\n",
- jinfo->name, info->name);
+ jinfo->name, info->name);
info = jinfo;
+ /* bind the flash info again */
+ nor->info = (struct flash_info *)info;
+ spi_nor_scan_delay(nor, info);
}
}
@@ -1547,6 +1856,56 @@ static const struct flash_info *spi_nor_match_id(const char *name)
return NULL;
}
+static int reset_chip(struct spi_nor *nor, struct flash_info *info)
+{
+ int ret = 0;
+
+ mutex_lock(&nor->lock);
+ /* Wait till previous write/erase is done. */
+ if (spi_nor_wait_till_ready(nor)) {
+ mutex_unlock(&nor->lock);
+ return 1;
+ }
+
+ switch (JEDEC_MFR(info)) {
+ case 0x9F: /* S25FL128/256S spansion */
+ ret = nor->write_reg(nor, 0xff, NULL, 0);
+ if (ret)
+ break;
+ ret = nor->write_reg(nor, 0xf0, NULL, 0);
+ break;
+
+ case 0xef: /*winbond*/
+ case 0xc8: /*GD*/
+ case 0x0B: /*XTX*/
+ case 0x5e: /*ZB*/
+ case 0x68: /*BY*/
+ ret = nor->write_reg(nor, 0x66, NULL, 0);
+ if (ret)
+ break;
+ ret = nor->write_reg(nor, 0x99, NULL, 0);
+ udelay(100);
+ break;
+ case CFI_MFR_MACRONIX:
+ case CFI_MFR_ST: /* Micron, actually */
+ default:
+ break;
+ }
+ mutex_unlock(&nor->lock);
+ return ret;
+}
+
+
+void spi_nor_restore(struct spi_nor *nor)
+{
+ if (nor->addr_width == 4)
+ set_4byte(nor, nor->info, 0);
+
+ if (reset_chip(nor, nor->info))
+ dev_err(nor->dev, "[spi nor] reset chip error...\n");
+}
+EXPORT_SYMBOL_GPL(spi_nor_restore);
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
MODULE_AUTHOR("Mike Lavender");
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 8cc7467b..76c87f7e 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -179,5 +179,6 @@ source "drivers/net/ethernet/via/Kconfig"
source "drivers/net/ethernet/wiznet/Kconfig"
source "drivers/net/ethernet/xilinx/Kconfig"
source "drivers/net/ethernet/xircom/Kconfig"
+source "drivers/net/ethernet/fullhan/Kconfig"
endif # ETHERNET
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index a09423df..81839293 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -89,3 +89,4 @@ obj-$(CONFIG_NET_VENDOR_VIA) += via/
obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
+obj-$(CONFIG_NET_VENDOR_FULLHAN) += fullhan/
diff --git a/drivers/net/ethernet/fullhan/Kconfig b/drivers/net/ethernet/fullhan/Kconfig
new file mode 100644
index 00000000..f8e45ab3
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/Kconfig
@@ -0,0 +1,49 @@
+#
+# Fullhan device configuration
+#
+
+config NET_VENDOR_FULLHAN
+ bool "Fullhan devices"
+ default y
+ depends on ARM
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Faraday cards. If you say Y, you will be asked for
+ your specific card in the following questions.
+
+if NET_VENDOR_FULLHAN
+
+config FH_GMAC
+ tristate "FH 10/100 Ethernet driver"
+ select MII
+ select PHYLIB
+ select CRC32
+ depends on NETDEVICES && HAS_IOMEM
+ help
+ This is the driver for the Ethernet IPs are built around a
+ Synopsys IP Core.
+
+config FH_GMAC_DA
+ bool "FH GMAC DMA arbitration scheme"
+ default n
+ help
+ Selecting this option, rx has priority over Tx (only for Giga
+ Ethernet device).
+ By default, the DMA arbitration scheme is based on Round-robin
+ (rx:tx priority is 1:1).
+
+
+config FH_EPHY
+ bool "FH Independent Research Ephy"
+ default n
+ help
+ This is the driver for Independent Research Ephy.
+
+
+endif # NET_VENDOR_FULLHAN
+
diff --git a/drivers/net/ethernet/fullhan/Makefile b/drivers/net/ethernet/fullhan/Makefile
new file mode 100644
index 00000000..4824c5cd
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/Makefile
@@ -0,0 +1,5 @@
+
+
+obj-$(CONFIG_FH_GMAC) += fh_gmac.o
+
+fh_gmac-objs := fh_gmac_dma.o fh_gmac_main.o fh_gmac_ethtool.o fh_gmac_phyt.o
\ No newline at end of file
diff --git a/drivers/net/ethernet/fullhan/fh_gmac.h b/drivers/net/ethernet/fullhan/fh_gmac.h
new file mode 100644
index 00000000..d255771d
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/fh_gmac.h
@@ -0,0 +1,273 @@
+/*
+ * fh_gmac.h
+ *
+ * Created on: May 22, 2014
+ * Author: duobao
+ */
+
+#ifndef FH_GMAC_H_
+#define FH_GMAC_H_
+
+#include <linux/phy.h>
+#include <linux/etherdevice.h>
+#include <mach/pmu.h>
+#include <linux/delay.h>
+#include "fh_gmac_phyt.h"
+#include "fh_gmac_dma.h"
+
+//GMAC-MAC
+#define REG_GMAC_CONFIG (0x0000)
+#define REG_GMAC_FRAME_FILTER (0x0004)
+#define REG_GMAC_HASH_HIGH (0x0008)
+#define REG_GMAC_HASH_LOW (0x000C)
+#define REG_GMAC_GMII_ADDRESS (0x0010)
+#define REG_GMAC_GMII_DATA (0x0014)
+#define REG_GMAC_FLOW_CTRL (0x0018)
+#define REG_GMAC_DEBUG (0x0024)
+#define REG_GMAC_MAC_HIGH (0x0040)
+#define REG_GMAC_MAC_LOW (0x0044)
+//GMAC-DMA
+#define REG_GMAC_BUS_MODE (0x1000)
+#define REG_GMAC_TX_POLL_DEMAND (0x1004)
+#define REG_GMAC_RX_POLL_DEMAND (0x1008)
+#define REG_GMAC_RX_DESC_ADDR (0x100C)
+#define REG_GMAC_TX_DESC_ADDR (0x1010)
+#define REG_GMAC_STATUS (0x1014)
+#define REG_GMAC_OP_MODE (0x1018)
+#define REG_GMAC_INTR_EN (0x101C)
+#define REG_GMAC_ERROR_COUNT (0x1020)
+#define REG_GMAC_AXI_BUS_MODE (0x1028)
+#define REG_GMAC_AXI_STATUS (0x102C)
+#define REG_GMAC_CURR_TX_DESC (0x1048)
+#define REG_GMAC_CURR_RX_DESC (0x104C)
+
+enum tx_dma_irq_status {
+ tx_hard_error = 1,
+ tx_hard_error_bump_tc = 2,
+ handle_tx_rx = 3,
+};
+
+enum rx_frame_status {
+ good_frame = 0,
+ discard_frame = 1,
+ csum_none = 2,
+ llc_snap = 4,
+};
+
+
+#define INTERNAL_PHY 0x55
+#define EXTERNAL_PHY 0xaa
+
+#define GMAC_MIN_ETHPKTSIZE (60) /* Minimum ethernet pkt size */
+#define GMAC_MAX_FRAME_SIZE (1500 + 14 + 4 + 4)
+
+#define BUFFER_SIZE_2K 2048
+#define BUFFER_SIZE_4K 4096
+#define BUFFER_SIZE_8K 8192
+#define BUFFER_SIZE_16K 16384
+
+#ifdef FH_GMAC_DMA_DEBUG
+#define GMAC_DMA_DBG(fmt, args...) printk(fmt, ## args)
+#else
+#define GMAC_DMA_DBG(fmt, args...) do { } while (0)
+#endif
+
+#ifdef FH_GMAC_XMIT_DEBUG
+#define TX_DBG(fmt, args...) printk(fmt, ## args)
+#else
+#define TX_DBG(fmt, args...) do { } while (0)
+#endif
+
+#ifdef FH_GMAC_RX_DEBUG
+#define RX_DBG(fmt, args...) printk(fmt, ## args)
+#else
+#define RX_DBG(fmt, args...) do { } while (0)
+#endif
+
+#define FH_GMAC_DEBUG (NETIF_MSG_DRV | \
+ NETIF_MSG_PROBE | \
+ NETIF_MSG_LINK | \
+ NETIF_MSG_TIMER | \
+ NETIF_MSG_IFDOWN | \
+ NETIF_MSG_IFUP | \
+ NETIF_MSG_RX_ERR | \
+ NETIF_MSG_TX_ERR | \
+ NETIF_MSG_TX_QUEUED | \
+ NETIF_MSG_INTR | \
+ NETIF_MSG_TX_DONE | \
+ NETIF_MSG_RX_STATUS | \
+ NETIF_MSG_PKTDATA | \
+ NETIF_MSG_HW | \
+ NETIF_MSG_WOL)
+
+enum {
+ gmac_gmii_clock_60_100,
+ gmac_gmii_clock_100_150,
+ gmac_gmii_clock_20_35,
+ gmac_gmii_clock_35_60,
+ gmac_gmii_clock_150_250,
+ gmac_gmii_clock_250_300
+};
+
+enum {
+ gmac_interrupt_all = 0x0001ffff,
+ gmac_interrupt_none = 0x0
+};
+
+typedef struct Gmac_Stats {
+ /* Transmit errors */
+ unsigned long tx_underflow
+ ____cacheline_aligned;
+ unsigned long tx_carrier;
+ unsigned long tx_losscarrier;
+ unsigned long tx_heartbeat;
+ unsigned long tx_deferred;
+ unsigned long tx_vlan;
+ unsigned long tx_jabber;
+ unsigned long tx_frame_flushed;
+ unsigned long tx_payload_error;
+ unsigned long tx_ip_header_error;
+ /* Receive errors */
+ unsigned long rx_desc;
+ unsigned long rx_partial;
+ unsigned long rx_runt;
+ unsigned long rx_toolong;
+ unsigned long rx_collision;
+ unsigned long rx_crc;
+ unsigned long rx_length;
+ unsigned long rx_mii;
+ unsigned long rx_multicast;
+ unsigned long rx_gmac_overflow;
+ unsigned long rx_watchdog;
+ unsigned long da_rx_filter_fail;
+ unsigned long sa_rx_filter_fail;
+ unsigned long rx_missed_cntr;
+ unsigned long rx_overflow_cntr;
+ /* Tx/Rx IRQ errors */
+ unsigned long tx_undeflow_irq;
+ unsigned long tx_process_stopped_irq;
+ unsigned long tx_jabber_irq;
+ unsigned long rx_overflow_irq;
+ unsigned long rx_buf_unav_irq;
+ unsigned long rx_process_stopped_irq;
+ unsigned long rx_watchdog_irq;
+ unsigned long tx_early_irq;
+ unsigned long fatal_bus_error_irq;
+ /* Extra info */
+ unsigned long threshold;
+ unsigned long tx_pkt_n;
+ unsigned long rx_pkt_n;
+ unsigned long poll_n;
+ unsigned long sched_timer_n;
+ unsigned long normal_irq_n;
+} Gmac_Stats;
+
+typedef struct Gmac_Object {
+ Gmac_Tx_DMA_Descriptors* tx_dma_descriptors ____cacheline_aligned_in_smp;
+ Gmac_Rx_DMA_Descriptors* rx_dma_descriptors ____cacheline_aligned_in_smp;
+ int full_duplex; //read only
+ int speed_100m; //read only
+
+ struct sk_buff_head rx_recycle;
+ struct sk_buff** rx_skbuff;
+ struct sk_buff** tx_skbuff;
+ dma_addr_t* rx_skbuff_dma;
+ __u32 cur_rx;
+ __u32 dirty_rx;
+ __u32 cur_tx;
+ __u32 dirty_tx;
+ dma_addr_t tx_bus_addr;
+ dma_addr_t rx_bus_addr;
+ __u32 dma_tx_size;
+ __u32 dma_rx_size;
+ __u32 dma_buf_sz;
+
+ spinlock_t lock;
+
+ void __iomem *remap_addr;
+ __u8 local_mac_address[6];
+ __u32 msg_enable;
+ struct device* dev;
+ struct net_device* ndev;
+ struct platform_device* pdev;
+ struct napi_struct napi ____cacheline_aligned_in_smp;
+ struct mii_bus *mii;
+ struct phy_device *phydev ____cacheline_aligned_in_smp;
+ Gmac_Stats stats;
+
+ int oldlink;
+ int speed;
+ int oldduplex;
+ __u32 flow_ctrl;
+ __u32 pause;
+
+ int wolopts;
+ int wolenabled;
+
+ int phy_interface;
+ struct fh_gmac_platform_data* priv_data;
+
+ struct clk* clk;
+
+ int phyid;
+
+ int phyreset_gpio;
+ int phyrxdv_gpio;
+ __u32 phy_sel;
+ int (*phy_reset)(struct Gmac_Object *p_gmac, __u32 phy_sel);
+#if defined CONFIG_FH_EPHY
+ void __iomem *ephy_base;
+ void __iomem *mdio_base;
+#endif
+} Gmac_Object;
+
+enum {
+ gmac_speed_10m,
+ gmac_speed_100m
+};
+
+#define TX_TIMEO 5000 /* default 5 seconds */
+
+#ifdef CONFIG_TINY_KERNEL
+#define DMA_RX_SIZE NAPI_POLL_WEIGHT
+#define DMA_TX_SIZE 32
+#else
+#define DMA_RX_SIZE 256
+#define DMA_TX_SIZE 256
+#endif
+
+#define FLOW_OFF 0
+#define FLOW_RX 4
+#define FLOW_TX 2
+#define FLOW_AUTO (FLOW_TX | FLOW_RX)
+#define PAUSE_TIME 0x200
+
+int fh_mdio_register(struct net_device *ndev);
+int fh_mdio_unregister(struct net_device *ndev);
+
+void GMAC_DMA_StartTx(Gmac_Object* pGmac);
+void GMAC_DMA_StopTx(Gmac_Object* pGmac);
+void GMAC_DMA_StartRx(Gmac_Object* pGmac);
+void GMAC_DMA_StopRx(Gmac_Object* pGmac);
+
+void fh_gmac_set_ethtool_ops(struct net_device *netdev);
+
+void GMAC_DMA_InitDescRings(struct net_device *ndev);
+int GMAC_DMA_Init(struct net_device *ndev, __u32 dma_tx, __u32 dma_rx);
+void GMAC_DMA_InitRxDesc(Gmac_Rx_DMA_Descriptors* desc, unsigned int size);
+void GMAC_DMA_InitTxDesc(Gmac_Tx_DMA_Descriptors* desc, unsigned int size);
+void GMAC_DMA_OpMode(Gmac_Object* pGmac);
+void GMAC_DMA_FreeDesc(Gmac_Object* pGmac);
+void GMAC_DMA_FreeRxSkbufs(Gmac_Object* pGmac);
+void GMAC_DMA_FreeTxSkbufs(Gmac_Object* pGmac);
+void GMAC_DMA_DisplayRxDesc(Gmac_Rx_DMA_Descriptors* desc, int size);
+void GMAC_DMA_DisplayTxDesc(Gmac_Tx_DMA_Descriptors* desc, int size);
+int GMAC_DMA_Interrupt(Gmac_Object* pGmac);
+int GMAC_DMA_TxStatus(Gmac_Object* pGmac, Gmac_Tx_DMA_Descriptors* desc);
+int GMAC_DMA_RxStatus(Gmac_Object* pGmac, Gmac_Rx_DMA_Descriptors* desc);
+void GMAC_DMA_ReleaseTxDesc(Gmac_Tx_DMA_Descriptors* desc);
+void GMAC_DMA_DiagnosticFrame(void *data, Gmac_Object* pGmac);
+void GMAC_FlowCtrl(Gmac_Object * pGmac, unsigned int duplex, unsigned int fc,
+ unsigned int pause_time);
+
+#endif /* FH_GMAC_H_ */
diff --git a/drivers/net/ethernet/fullhan/fh_gmac_dma.c b/drivers/net/ethernet/fullhan/fh_gmac_dma.c
new file mode 100644
index 00000000..77c31e11
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/fh_gmac_dma.c
@@ -0,0 +1,525 @@
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <asm/dma-mapping.h>
+#include "fh_gmac.h"
+#include "fh_gmac_dma.h"
+
+void GMAC_DMA_ReleaseTxDesc(Gmac_Tx_DMA_Descriptors * desc)
+{
+ int ter = desc->desc1.bit.end_of_ring;
+ desc->desc0.dw = 0;
+ desc->desc1.dw = 0;
+ /* set termination field */
+ desc->desc1.bit.end_of_ring = ter;
+}
+
+void GMAC_DMA_DisplayRxDesc(Gmac_Rx_DMA_Descriptors * desc, int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ pr_info("\t%d [0x%x]: DES0=0x%x DES1=0x%x DES2=0x%x DES3=0x%x",
+ i, (__u32) (&desc[i]), desc[i].desc0.dw,
+ desc[i].desc1.dw, desc[i].desc2.dw, desc[i].desc3.dw);
+ pr_info("\n");
+ }
+}
+
+void GMAC_DMA_DisplayTxDesc(Gmac_Tx_DMA_Descriptors * desc, int size)
+{
+ int i;
+ pr_info("Tx desc:\n");
+ for (i = 0; i < size; i++) {
+ pr_info("\t%d [0x%x]: DES0=0x%x DES1=0x%x BUF1=0x%x BUF2=0x%x",
+ i, (__u32) & desc[i], desc[i].desc0.dw,
+ desc[i].desc1.dw, desc[i].desc2.dw, desc[i].desc3.dw);
+ pr_info("\n");
+ }
+}
+
+void GMAC_DMA_InitRxDesc(Gmac_Rx_DMA_Descriptors * desc, __u32 size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ desc->desc0.bit.own = 1;
+ desc->desc1.bit.buffer1_size = BUFFER_SIZE_2K - 1;
+ if (i == size - 1) {
+ desc->desc1.bit.end_of_ring = 1;
+ }
+ desc++;
+ }
+}
+
+void GMAC_DMA_InitTxDesc(Gmac_Tx_DMA_Descriptors * desc, __u32 size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ desc->desc0.bit.own = 0;
+ if (i == size - 1) {
+ desc->desc1.bit.end_of_ring = 1;
+ }
+ desc++;
+ }
+}
+
+void GMAC_DMA_OpMode(Gmac_Object * pGmac)
+{
+
+ //op mode, reg 6
+ //transmit_store_forward
+ //receive_store_forward
+ writel(0 << 25 | 1 << 21 | 0 << 2 | 0 << 14,
+ pGmac->remap_addr + REG_GMAC_OP_MODE);
+}
+
+void GMAC_DMA_InitDescRings(struct net_device *ndev)
+{
+ int i;
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ struct sk_buff *skb;
+ __u32 txsize = pGmac->dma_tx_size;
+ __u32 rxsize = pGmac->dma_rx_size;
+ __u32 bfsize = pGmac->dma_buf_sz;
+
+ pGmac->rx_skbuff_dma = kmalloc(rxsize * sizeof(dma_addr_t), GFP_KERNEL);
+ pGmac->rx_skbuff =
+ kmalloc(sizeof(struct sk_buff *) * rxsize, GFP_KERNEL);
+ pGmac->rx_dma_descriptors =
+ (Gmac_Rx_DMA_Descriptors *) dma_alloc_coherent(pGmac->dev,
+ rxsize *
+ sizeof
+ (Gmac_Rx_DMA_Descriptors),
+ &pGmac->rx_bus_addr,
+ GFP_KERNEL);
+ pGmac->tx_skbuff =
+ kmalloc(sizeof(struct sk_buff *) * txsize, GFP_KERNEL);
+ pGmac->tx_dma_descriptors =
+ (Gmac_Tx_DMA_Descriptors *) dma_alloc_coherent(pGmac->dev,
+ txsize *
+ sizeof
+ (Gmac_Tx_DMA_Descriptors),
+ &pGmac->tx_bus_addr,
+ GFP_KERNEL);
+
+ if ((pGmac->rx_dma_descriptors == NULL)
+ || (pGmac->tx_dma_descriptors == NULL)) {
+ pr_err("%s:ERROR allocating the DMA Tx/Rx desc\n", __func__);
+ return;
+ }
+
+ pr_debug("fh gmac (%s) DMA desc rings: virt addr (Rx %p, "
+ "Tx %p)\n\tDMA phy addr (Rx 0x%08x, Tx 0x%08x)\n",
+ ndev->name, pGmac->rx_dma_descriptors,
+ pGmac->tx_dma_descriptors, (__u32) pGmac->rx_bus_addr,
+ (__u32) pGmac->tx_bus_addr);
+
+ for (i = 0; i < rxsize; i++) {
+ Gmac_Rx_DMA_Descriptors *desc = pGmac->rx_dma_descriptors + i;
+
+ skb = netdev_alloc_skb_ip_align(ndev, bfsize);
+ if (unlikely(skb == NULL)) {
+ pr_err("%s: Rx init fails; skb is NULL\n", __func__);
+ break;
+ }
+ pGmac->rx_skbuff[i] = skb;
+ pGmac->rx_skbuff_dma[i] =
+ dma_map_single(pGmac->dev, skb->data, bfsize,
+ DMA_FROM_DEVICE);
+
+ desc->desc2.dw = pGmac->rx_skbuff_dma[i];
+ }
+ pGmac->cur_rx = 0;
+ pGmac->dirty_rx = (__u32) (i - rxsize);
+
+ pGmac->dma_buf_sz = bfsize;
+
+ /* TX INITIALIZATION */
+ for (i = 0; i < txsize; i++) {
+ pGmac->tx_skbuff[i] = NULL;
+ pGmac->tx_dma_descriptors[i].desc2.dw = 0;
+ }
+ pGmac->dirty_tx = 0;
+ pGmac->cur_tx = 0;
+
+ /* Clear the Rx/Tx descriptors */
+ GMAC_DMA_InitRxDesc(pGmac->rx_dma_descriptors, rxsize);
+ GMAC_DMA_InitTxDesc(pGmac->tx_dma_descriptors, txsize);
+#ifdef FH_GMAC_DMA_DEBUG
+ if (netif_msg_hw(pGmac)) {
+ pr_info("RX descriptor ring:\n");
+ GMAC_DMA_DisplayRxDesc(pGmac->rx_dma_descriptors, rxsize);
+ pr_info("TX descriptor ring:\n");
+ GMAC_DMA_DisplayTxDesc(pGmac->tx_dma_descriptors, txsize);
+ }
+#endif
+}
+
+void GMAC_DMA_FreeRxSkbufs(Gmac_Object * pGmac)
+{
+ int i;
+
+ for (i = 0; i < pGmac->dma_rx_size; i++) {
+ if (pGmac->rx_skbuff[i]) {
+ dma_unmap_single(pGmac->dev, pGmac->rx_skbuff_dma[i],
+ pGmac->dma_buf_sz, DMA_FROM_DEVICE);
+ dev_kfree_skb_any(pGmac->rx_skbuff[i]);
+ }
+ pGmac->rx_skbuff[i] = NULL;
+ }
+}
+
+void GMAC_DMA_FreeTxSkbufs(Gmac_Object * pGmac)
+{
+ int i;
+
+ for (i = 0; i < pGmac->dma_tx_size; i++) {
+ if (pGmac->tx_skbuff[i] != NULL) {
+ Gmac_Tx_DMA_Descriptors *desc =
+ pGmac->tx_dma_descriptors + i;
+ if (desc->desc2.dw) {
+ __u32 size;
+ size = desc->desc1.bit.buffer1_size;
+ dma_unmap_single(pGmac->dev, desc->desc2.dw,
+ size, DMA_TO_DEVICE);
+ }
+ dev_kfree_skb_any(pGmac->tx_skbuff[i]);
+ pGmac->tx_skbuff[i] = NULL;
+ }
+ }
+}
+
+void GMAC_DMA_FreeDesc(Gmac_Object * pGmac)
+{
+ /* Release the DMA TX/RX socket buffers */
+ GMAC_DMA_FreeRxSkbufs(pGmac);
+ GMAC_DMA_FreeTxSkbufs(pGmac);
+
+ /* Free the region of consistent memory previously allocated for
+ * the DMA */
+ dma_free_coherent(pGmac->dev,
+ pGmac->dma_tx_size * sizeof(Gmac_Tx_DMA_Descriptors),
+ pGmac->tx_dma_descriptors, pGmac->tx_bus_addr);
+ dma_free_coherent(pGmac->dev,
+ pGmac->dma_rx_size * sizeof(Gmac_Tx_DMA_Descriptors),
+ pGmac->rx_dma_descriptors, pGmac->rx_bus_addr);
+ kfree(pGmac->rx_skbuff_dma);
+ kfree(pGmac->rx_skbuff);
+ kfree(pGmac->tx_skbuff);
+}
+
+int GMAC_DMA_Init(struct net_device *ndev, __u32 dma_tx, __u32 dma_rx)
+{
+ Gmac_Object *pGmac = netdev_priv(ndev);
+#ifdef GMAC_RESET
+ int limit;
+
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_BUS_MODE);
+ reg |= 0x1;
+ writel(reg, pGmac->remap_addr + REG_GMAC_BUS_MODE);
+
+ limit = 10;
+ while (limit--) {
+ if (!(readl(pGmac->remap_addr + REG_GMAC_BUS_MODE) & 0x1)) {
+ break;
+ }
+ mdelay(10);
+ }
+ if (limit < 0)
+ return -EBUSY;
+#endif
+ //initialize dma bus mode reg0
+ //8xpbl
+ //no address_aligned_beats
+ //fixed_burst
+#ifdef CONFIG_EMULATION
+ writel(0 << 25 | 0 << 24 | 0 << 16 | 32 << 8,
+ pGmac->remap_addr + REG_GMAC_BUS_MODE);
+#else
+ writel(0 << 25 | 0 << 24 | 1 << 16 | 32 << 8,
+ pGmac->remap_addr + REG_GMAC_BUS_MODE);
+#endif
+ writel(0x1a061, pGmac->remap_addr + REG_GMAC_INTR_EN);
+ /* The base address of the RX/TX descriptor lists must be written into
+ * DMA CSR3 and CSR4, respectively. */
+ writel(dma_rx, pGmac->remap_addr + REG_GMAC_RX_DESC_ADDR);
+ writel(dma_tx, pGmac->remap_addr + REG_GMAC_TX_DESC_ADDR);
+
+ return 0;
+}
+
+void GMAC_DMA_StartTx(Gmac_Object * pGmac)
+{
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE);
+ reg |= 1 << 13;
+ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE);
+}
+
+void GMAC_DMA_StopTx(Gmac_Object * pGmac)
+{
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE);
+ reg &= ~(1 << 13);
+ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE);
+}
+
+void GMAC_DMA_StartRx(Gmac_Object * pGmac)
+{
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE);
+ reg |= 1 << 1;
+ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE);
+}
+
+void GMAC_DMA_StopRx(Gmac_Object * pGmac)
+{
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_OP_MODE);
+ reg &= ~(1 << 1);
+ writel(reg, pGmac->remap_addr + REG_GMAC_OP_MODE);
+}
+
+#ifdef FH_GMAC_DMA_DEBUG
+static void GMAC_DMA_ShowTxState(__u32 status)
+{
+ __u32 state;
+ state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT;
+
+ switch (state) {
+ case 0:
+ pr_info("- TX (Stopped): Reset or Stop command\n");
+ break;
+ case 1:
+ pr_info("- TX (Running):Fetching the Tx desc\n");
+ break;
+ case 2:
+ pr_info("- TX (Running): Waiting for end of tx\n");
+ break;
+ case 3:
+ pr_info("- TX (Running): Reading the data "
+ "and queuing the data into the Tx buf\n");
+ break;
+ case 6:
+ pr_info("- TX (Suspended): Tx Buff Underflow "
+ "or an unavailable Transmit descriptor\n");
+ break;
+ case 7:
+ pr_info("- TX (Running): Closing Tx descriptor\n");
+ break;
+ default:
+ break;
+ }
+}
+
+static void GMAC_DMA_ShowRxState(__u32 status)
+{
+ __u32 state;
+ state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT;
+
+ switch (state) {
+ case 0:
+ pr_info("- RX (Stopped): Reset or Stop command\n");
+ break;
+ case 1:
+ pr_info("- RX (Running): Fetching the Rx desc\n");
+ break;
+ case 2:
+ pr_info("- RX (Running):Checking for end of pkt\n");
+ break;
+ case 3:
+ pr_info("- RX (Running): Waiting for Rx pkt\n");
+ break;
+ case 4:
+ pr_info("- RX (Suspended): Unavailable Rx buf\n");
+ break;
+ case 5:
+ pr_info("- RX (Running): Closing Rx descriptor\n");
+ break;
+ case 6:
+ pr_info("- RX(Running): Flushing the current frame"
+ " from the Rx buf\n");
+ break;
+ case 7:
+ pr_info("- RX (Running): Queuing the Rx frame"
+ " from the Rx buf into memory\n");
+ break;
+ default:
+ break;
+ }
+}
+#endif
+
+int GMAC_DMA_Interrupt(Gmac_Object * pGmac)
+{
+ int ret = 0;
+ Gmac_Stats *gmac_stats = &pGmac->stats;
+ /* read the status register (CSR5) */
+ __u32 intr_status;
+ intr_status = readl(pGmac->remap_addr + REG_GMAC_STATUS);
+
+ GMAC_DMA_DBG("%s: [GMAC_STATUS: 0x%08x]\n", __func__, intr_status);
+#ifdef FH_GMAC_DMA_DEBUG
+ /* It displays the DMA process states (CSR5 register) */
+ GMAC_DMA_ShowTxState(intr_status);
+ GMAC_DMA_ShowRxState(intr_status);
+#endif
+ /* ABNORMAL interrupts */
+ if (unlikely(intr_status & DMA_STATUS_AIS)) {
+ GMAC_DMA_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: ");
+ if (unlikely(intr_status & DMA_STATUS_UNF)) {
+ GMAC_DMA_DBG(KERN_INFO "transmit underflow\n");
+ ret = tx_hard_error_bump_tc;
+ gmac_stats->tx_undeflow_irq++;
+ }
+ if (unlikely(intr_status & DMA_STATUS_TJT)) {
+ GMAC_DMA_DBG(KERN_INFO "transmit jabber\n");
+ gmac_stats->tx_jabber_irq++;
+ }
+ if (unlikely(intr_status & DMA_STATUS_OVF)) {
+ GMAC_DMA_DBG(KERN_INFO "recv overflow\n");
+ gmac_stats->rx_overflow_irq++;
+ }
+ if (unlikely(intr_status & DMA_STATUS_RU)) {
+ GMAC_DMA_DBG(KERN_INFO "receive buffer unavailable\n");
+ gmac_stats->rx_buf_unav_irq++;
+ }
+ if (unlikely(intr_status & DMA_STATUS_RPS)) {
+ GMAC_DMA_DBG(KERN_INFO "receive process stopped\n");
+ gmac_stats->rx_process_stopped_irq++;
+ }
+ if (unlikely(intr_status & DMA_STATUS_RWT)) {
+ GMAC_DMA_DBG(KERN_INFO "receive watchdog\n");
+ gmac_stats->rx_watchdog_irq++;
+ }
+ if (unlikely(intr_status & DMA_STATUS_ETI)) {
+ GMAC_DMA_DBG(KERN_INFO "transmit early interrupt\n");
+ gmac_stats->tx_early_irq++;
+ }
+ if (unlikely(intr_status & DMA_STATUS_TPS)) {
+ GMAC_DMA_DBG(KERN_INFO "transmit process stopped\n");
+ gmac_stats->tx_process_stopped_irq++;
+ ret = tx_hard_error;
+ }
+ if (unlikely(intr_status & DMA_STATUS_FBI)) {
+ GMAC_DMA_DBG(KERN_INFO "fatal bus error\n");
+ gmac_stats->fatal_bus_error_irq++;
+ ret = tx_hard_error;
+ }
+ }
+ /* TX/RX NORMAL interrupts */
+ if (intr_status & DMA_STATUS_NIS) {
+ gmac_stats->normal_irq_n++;
+ if (likely((intr_status & DMA_STATUS_RI) ||
+ (intr_status & (DMA_STATUS_TI))))
+ ret = handle_tx_rx;
+ }
+ /* Optional hardware blocks, interrupts should be disabled */
+ if (unlikely(intr_status &
+ (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
+ pr_info("%s: unexpected status %08x\n", __func__, intr_status);
+
+ /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
+ writel(intr_status & 0x1ffff, pGmac->remap_addr + REG_GMAC_STATUS);
+ GMAC_DMA_DBG(KERN_INFO "\n\n");
+
+ return ret;
+}
+
+int GMAC_DMA_TxStatus(Gmac_Object * pGmac, Gmac_Tx_DMA_Descriptors * desc)
+{
+ int ret = 0;
+ struct net_device_stats *stats = &pGmac->ndev->stats;
+ Gmac_Stats *gmac_stats = &pGmac->stats;
+
+ if (unlikely(desc->desc0.bit.error_summary)) {
+ if (unlikely(desc->desc0.bit.underflow_error)) {
+ gmac_stats->tx_underflow++;
+ stats->tx_fifo_errors++;
+ }
+ if (unlikely(desc->desc0.bit.no_carrier)) {
+ gmac_stats->tx_carrier++;
+ stats->tx_carrier_errors++;
+ }
+ if (unlikely(desc->desc0.bit.loss_of_carrier)) {
+ gmac_stats->tx_losscarrier++;
+ stats->tx_carrier_errors++;
+ }
+ if (unlikely((desc->desc0.bit.excessive_deferral) ||
+ (desc->desc0.bit.excessive_collision) ||
+ (desc->desc0.bit.late_collision)))
+ stats->collisions += desc->desc0.bit.collision_count;
+ ret = -1;
+ }
+ if (unlikely(desc->desc0.bit.deferred))
+ gmac_stats->tx_deferred++;
+
+ return ret;
+}
+
+int GMAC_DMA_RxStatus(Gmac_Object * pGmac, Gmac_Rx_DMA_Descriptors * desc)
+{
+ int ret = csum_none;
+ struct net_device_stats *stats = &pGmac->ndev->stats;
+ Gmac_Stats *gmac_stats = &pGmac->stats;
+
+ if (unlikely(desc->desc0.bit.last_descriptor == 0)) {
+ pr_warning("ndesc Error: Oversized Ethernet "
+ "frame spanned multiple buffers\n");
+ stats->rx_length_errors++;
+ return discard_frame;
+ }
+
+ if (unlikely(desc->desc0.bit.error_summary)) {
+ if (unlikely(desc->desc0.bit.descriptor_error))
+ gmac_stats->rx_desc++;
+ if (unlikely(desc->desc0.bit.ipc_chksum_error_giant_frame))
+ gmac_stats->rx_toolong++;
+ if (unlikely(desc->desc0.bit.late_collision)) {
+ gmac_stats->rx_collision++;
+ stats->collisions++;
+ }
+ if (unlikely(desc->desc0.bit.crc_error)) {
+ gmac_stats->rx_crc++;
+ stats->rx_crc_errors++;
+ }
+ ret = discard_frame;
+ }
+
+ if (pGmac->phy_interface == PHY_INTERFACE_MODE_MII)
+ if (unlikely(desc->desc0.bit.dribble_error))
+ ret = discard_frame;
+
+ if (unlikely(desc->desc0.bit.length_error)) {
+ gmac_stats->rx_length++;
+ ret = discard_frame;
+ }
+
+ return ret;
+}
+
+void GMAC_DMA_DiagnosticFrame(void *data, Gmac_Object * pGmac)
+{
+ struct net_device_stats *stats = (struct net_device_stats *)data;
+ Gmac_Stats *gmac_stats = &pGmac->stats;
+ __u32 csr8 = readl(pGmac->remap_addr + REG_GMAC_ERROR_COUNT);
+
+ if (unlikely(csr8)) {
+ //Overflow bit for FIFO Overflow Counter
+ if (csr8 & 0x10000000) {
+ stats->rx_over_errors += 0x800;
+ gmac_stats->rx_overflow_cntr += 0x800;
+ } else {
+ unsigned int ove_cntr;
+ //indicates the number of frames missed by the application
+ ove_cntr = ((csr8 & 0x0ffe0000) >> 17);
+ stats->rx_over_errors += ove_cntr;
+ gmac_stats->rx_overflow_cntr += ove_cntr;
+ }
+
+ //Overflow bit for Missed Frame Counter
+ if (csr8 & 0x10000) {
+ stats->rx_missed_errors += 0xffff;
+ gmac_stats->rx_missed_cntr += 0xffff;
+ } else {
+ //indicates the number of frames missed by the controller
+ unsigned int miss_f = (csr8 & 0xffff);
+ stats->rx_missed_errors += miss_f;
+ gmac_stats->rx_missed_cntr += miss_f;
+ }
+ }
+}
diff --git a/drivers/net/ethernet/fullhan/fh_gmac_dma.h b/drivers/net/ethernet/fullhan/fh_gmac_dma.h
new file mode 100644
index 00000000..43c02761
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/fh_gmac_dma.h
@@ -0,0 +1,183 @@
+/*
+ * fh_gmac_dma.h
+ *
+ * Created on: May 22, 2014
+ * Author: duobao
+ */
+
+#ifndef FH_GMAC_DMA_H_
+#define FH_GMAC_DMA_H_
+
+
+
+/* DMA Status register defines */
+#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */
+#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
+#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
+#define DMA_STATUS_GMI 0x08000000
+#define DMA_STATUS_GLI 0x04000000
+#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT 20
+#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT 17
+#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */
+#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */
+#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */
+#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */
+#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */
+#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */
+#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */
+#define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */
+
+typedef union
+{
+ struct
+ {
+ __u32 deferred :1; //0~31
+ __u32 underflow_error :1;
+ __u32 excessive_deferral :1;
+ __u32 collision_count :4;
+ __u32 vlan_frame :1;
+ __u32 excessive_collision :1;
+ __u32 late_collision :1;
+ __u32 no_carrier :1;
+ __u32 loss_of_carrier :1;
+ __u32 payload_checksum_error :1;
+ __u32 frame_flushed :1;
+ __u32 jabber_timeout :1;
+ __u32 error_summary :1;
+ __u32 ip_header_error :1;
+ __u32 tx_timestamp_status :1;
+ __u32 reserved_30_18 :13;
+ __u32 own :1;
+ }bit;
+ __u32 dw;
+}Gmac_Tx_Descriptor0;
+
+typedef union
+{
+ struct
+ {
+ __u32 buffer1_size :11; //0~31
+ __u32 buffer2_size :11;
+ __u32 timestamp_enable :1;
+ __u32 disable_padding :1;
+ __u32 second_address_chained :1;
+ __u32 end_of_ring :1;
+ __u32 disable_crc :1;
+ __u32 checksum_insertion_ctrl :2;
+ __u32 first_segment :1;
+ __u32 last_segment :1;
+ __u32 intr_on_completion :1;
+ }bit;
+ __u32 dw;
+}Gmac_Tx_Descriptor1;
+
+typedef union
+{
+ struct
+ {
+ __u32 buffer_address_pointer :32; //0~31
+ }bit;
+ __u32 dw;
+}Gmac_Tx_Descriptor2;
+
+typedef union
+{
+ struct
+ {
+ __u32 buffer_address_pointer :32; //0~31
+ }bit;
+ __u32 dw;
+}Gmac_Tx_Descriptor3;
+
+typedef union
+{
+ struct
+ {
+ __u32 mac_addr_payload_chksum_error :1; //0
+ __u32 crc_error :1; //1
+ __u32 dribble_error :1; //2
+ __u32 receive_error :1; //3
+ __u32 watchdog_timeout :1; //4
+ __u32 frame_type :1; //5
+ __u32 late_collision :1; //6
+ __u32 ipc_chksum_error_giant_frame :1; //7
+ __u32 last_descriptor :1; //8
+ __u32 first_descriptor :1; //9
+ __u32 vlan_tag :1; //10
+ __u32 overflow_error :1; //11
+ __u32 length_error :1; //12
+ __u32 sa_filter_fail :1; //13
+ __u32 descriptor_error :1; //14
+ __u32 error_summary :1; //15
+ __u32 frame_length :14;//16~29
+ __u32 da_filter_fail :1; //30
+ __u32 own :1; //31
+ }bit;
+ __u32 dw;
+}Gmac_Rx_Descriptor0;
+
+typedef union
+{
+ struct
+ {
+ __u32 buffer1_size :11; //0~10
+ __u32 buffer2_size :11; //11~21
+ __u32 reserved_23_22 :2; //22~23
+ __u32 second_address_chained :1; //24
+ __u32 end_of_ring :1; //25
+ __u32 reserved_30_26 :5; //26~30
+ __u32 disable_intr_on_completion :1; //31
+ }bit;
+ __u32 dw;
+}Gmac_Rx_Descriptor1;
+
+typedef union
+{
+ struct
+ {
+ __u32 buffer_address_pointer :32; //0~31
+ }bit;
+ __u32 dw;
+}Gmac_Rx_Descriptor2;
+
+typedef union
+{
+ struct
+ {
+ __u32 buffer_address_pointer :32; //0~31
+ }bit;
+ __u32 dw;
+}Gmac_Rx_Descriptor3;
+
+typedef struct
+{
+ Gmac_Tx_Descriptor0 desc0; /* control and status information of descriptor */
+ Gmac_Tx_Descriptor1 desc1; /* buffer sizes */
+ Gmac_Tx_Descriptor2 desc2; /* physical address of the buffer 1 */
+ Gmac_Tx_Descriptor3 desc3; /* physical address of the buffer 2 */
+}Gmac_Tx_DMA_Descriptors;
+
+typedef struct
+{
+ Gmac_Rx_Descriptor0 desc0; /* control and status information of descriptor */
+ Gmac_Rx_Descriptor1 desc1; /* buffer sizes */
+ Gmac_Rx_Descriptor2 desc2; /* physical address of the buffer 1 */
+ Gmac_Rx_Descriptor3 desc3; /* physical address of the buffer 2 */
+}Gmac_Rx_DMA_Descriptors;
+
+
+
+#endif /* FH_GMAC_DMA_H_ */
diff --git a/drivers/net/ethernet/fullhan/fh_gmac_ethtool.c b/drivers/net/ethernet/fullhan/fh_gmac_ethtool.c
new file mode 100644
index 00000000..d04ddbea
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/fh_gmac_ethtool.c
@@ -0,0 +1,315 @@
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include "fh_gmac.h"
+
+#define REG_SPACE_SIZE 0x1054
+#define GMAC_ETHTOOL_NAME "fh_gmac"
+
+struct gmac_stats
+{
+ char stat_string[ETH_GSTRING_LEN];
+ int sizeof_stat;
+ int stat_offset;
+};
+
+#define FH_GMAC_STAT(m) \
+ { #m, FIELD_SIZEOF(Gmac_Stats, m), \
+ offsetof(Gmac_Object, stats.m)}
+
+static const struct gmac_stats gmac_gstrings_stats[] =
+{
+ FH_GMAC_STAT(tx_underflow),
+ FH_GMAC_STAT(tx_carrier),
+ FH_GMAC_STAT(tx_losscarrier),
+ FH_GMAC_STAT(tx_heartbeat),
+ FH_GMAC_STAT(tx_deferred),
+ FH_GMAC_STAT(tx_vlan),
+ FH_GMAC_STAT(tx_jabber),
+ FH_GMAC_STAT(tx_frame_flushed),
+ FH_GMAC_STAT(tx_payload_error),
+ FH_GMAC_STAT(tx_ip_header_error),
+ FH_GMAC_STAT(rx_desc),
+ FH_GMAC_STAT(rx_partial),
+ FH_GMAC_STAT(rx_runt),
+ FH_GMAC_STAT(rx_toolong),
+ FH_GMAC_STAT(rx_collision),
+ FH_GMAC_STAT(rx_crc),
+ FH_GMAC_STAT(rx_length),
+ FH_GMAC_STAT(rx_mii),
+ FH_GMAC_STAT(rx_multicast),
+ FH_GMAC_STAT(rx_gmac_overflow),
+ FH_GMAC_STAT(rx_watchdog),
+ FH_GMAC_STAT(da_rx_filter_fail),
+ FH_GMAC_STAT(sa_rx_filter_fail),
+ FH_GMAC_STAT(rx_missed_cntr),
+ FH_GMAC_STAT(rx_overflow_cntr),
+ FH_GMAC_STAT(tx_undeflow_irq),
+ FH_GMAC_STAT(tx_process_stopped_irq),
+ FH_GMAC_STAT(tx_jabber_irq),
+ FH_GMAC_STAT(rx_overflow_irq),
+ FH_GMAC_STAT(rx_buf_unav_irq),
+ FH_GMAC_STAT(rx_process_stopped_irq),
+ FH_GMAC_STAT(rx_watchdog_irq),
+ FH_GMAC_STAT(tx_early_irq),
+ FH_GMAC_STAT(fatal_bus_error_irq),
+ FH_GMAC_STAT(threshold),
+ FH_GMAC_STAT(tx_pkt_n),
+ FH_GMAC_STAT(rx_pkt_n),
+ FH_GMAC_STAT(poll_n),
+ FH_GMAC_STAT(sched_timer_n),
+ FH_GMAC_STAT(normal_irq_n),
+};
+#define FH_GMAC_STATS_LEN ARRAY_SIZE(gmac_gstrings_stats)
+
+static void gmac_ethtool_getdrvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, GMAC_ETHTOOL_NAME);
+
+ strcpy(info->version, "0.0.1");
+ info->fw_version[0] = '\0';
+ info->n_stats = FH_GMAC_STATS_LEN;
+}
+
+static int gmac_ethtool_getsettings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ struct phy_device *phy = pGmac->phydev;
+ int rc;
+ if (phy == NULL)
+ {
+ pr_err("%s: %s: PHY is not registered\n",
+ __func__, ndev->name);
+ return -ENODEV;
+ }
+ if (!netif_running(ndev))
+ {
+ pr_err("%s: interface is disabled: we cannot track "
+ "link speed / duplex setting\n", ndev->name);
+ return -EBUSY;
+ }
+ cmd->transceiver = XCVR_INTERNAL;
+ spin_lock_irq(&pGmac->lock);
+ rc = phy_ethtool_gset(phy, cmd);
+ spin_unlock_irq(&pGmac->lock);
+ return rc;
+}
+
+static int gmac_ethtool_setsettings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ struct phy_device *phy = pGmac->phydev;
+ int rc;
+
+ spin_lock(&pGmac->lock);
+ rc = phy_ethtool_sset(phy, cmd);
+ spin_unlock(&pGmac->lock);
+
+ return rc;
+}
+
+static __u32 gmac_ethtool_getmsglevel(struct net_device *ndev)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ return pGmac->msg_enable;
+}
+
+static void gmac_ethtool_setmsglevel(struct net_device *ndev, __u32 level)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ pGmac->msg_enable = level;
+
+}
+
+static int gmac_check_if_running(struct net_device *ndev)
+{
+ if (!netif_running(ndev))
+ return -EBUSY;
+ return 0;
+}
+
+static int gmac_ethtool_get_regs_len(struct net_device *ndev)
+{
+ return REG_SPACE_SIZE;
+}
+
+static void gmac_ethtool_gregs(struct net_device *ndev, struct ethtool_regs *regs, void *space)
+{
+ int i;
+ __u32 *reg_space = (__u32 *) space;
+
+ Gmac_Object* pGmac = netdev_priv(ndev);
+
+ memset(reg_space, 0x0, REG_SPACE_SIZE);
+
+ /* MAC registers */
+ for (i = 0; i < 55; i++)
+ reg_space[i] = readl(pGmac->remap_addr + (i * 4));
+ /* DMA registers */
+ for (i = 0; i < 22; i++)
+ reg_space[i + 55] = readl(pGmac->remap_addr + (REG_GMAC_BUS_MODE + (i * 4)));
+}
+
+static void gmac_get_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+
+ spin_lock(&pGmac->lock);
+
+ pause->rx_pause = 0;
+ pause->tx_pause = 0;
+ pause->autoneg = pGmac->phydev->autoneg;
+
+ if (pGmac->flow_ctrl & FLOW_RX)
+ pause->rx_pause = 1;
+ if (pGmac->flow_ctrl & FLOW_TX)
+ pause->tx_pause = 1;
+
+ spin_unlock(&pGmac->lock);
+}
+
+static int gmac_set_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ struct phy_device *phy = pGmac->phydev;
+ int new_pause = FLOW_OFF;
+ int ret = 0;
+
+ spin_lock(&pGmac->lock);
+
+ if (pause->rx_pause)
+ new_pause |= FLOW_RX;
+ if (pause->tx_pause)
+ new_pause |= FLOW_TX;
+
+ pGmac->flow_ctrl = new_pause;
+ phy->autoneg = pause->autoneg;
+
+ if (phy->autoneg)
+ {
+ if (netif_running(ndev))
+ ret = phy_start_aneg(phy);
+ }
+ else
+ {
+ GMAC_FlowCtrl(pGmac, phy->duplex, pGmac->flow_ctrl, pGmac->pause);
+ }
+ spin_unlock(&pGmac->lock);
+ return ret;
+}
+
+static void gmac_get_ethtool_stats(struct net_device *ndev, struct ethtool_stats *dummy, __u64 *data)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ int i;
+
+ /* Update HW stats if supported */
+ GMAC_DMA_DiagnosticFrame(&ndev->stats, pGmac);
+
+ for (i = 0; i < FH_GMAC_STATS_LEN; i++)
+ {
+ char *p = (char *)pGmac + gmac_gstrings_stats[i].stat_offset;
+ data[i] = (gmac_gstrings_stats[i].sizeof_stat ==
+ sizeof(__u64)) ? (*(__u64 *)p) : (*(__u32 *)p);
+ }
+}
+
+static int gmac_get_sset_count(struct net_device *netdev, int sset)
+{
+ switch (sset)
+ {
+ case ETH_SS_STATS:
+ return FH_GMAC_STATS_LEN;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void gmac_get_strings(struct net_device *ndev, __u32 stringset, __u8 *data)
+{
+ int i;
+ __u8 *p = data;
+
+ switch (stringset)
+ {
+ case ETH_SS_STATS:
+ for (i = 0; i < FH_GMAC_STATS_LEN; i++)
+ {
+ memcpy(p, gmac_gstrings_stats[i].stat_string, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+}
+
+/* Currently only support WOL through Magic packet. */
+static void gmac_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+
+ spin_lock_irq(&pGmac->lock);
+ if (device_can_wakeup(pGmac->dev))
+ {
+ wol->supported = WAKE_MAGIC | WAKE_UCAST;
+ wol->wolopts = pGmac->wolopts;
+ }
+ spin_unlock_irq(&pGmac->lock);
+}
+
+static int gmac_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ __u32 support = WAKE_MAGIC | WAKE_UCAST;
+
+ if (!device_can_wakeup(pGmac->dev))
+ return -EINVAL;
+
+ if (wol->wolopts & ~support)
+ return -EINVAL;
+
+ if (wol->wolopts)
+ {
+ pr_info("fh_gmac: wakeup enable\n");
+ device_set_wakeup_enable(pGmac->dev, 1);
+ enable_irq_wake(ndev->irq);
+ }
+ else
+ {
+ device_set_wakeup_enable(pGmac->dev, 0);
+ disable_irq_wake(ndev->irq);
+ }
+
+ spin_lock_irq(&pGmac->lock);
+ pGmac->wolopts = wol->wolopts;
+ spin_unlock_irq(&pGmac->lock);
+
+ return 0;
+}
+
+static struct ethtool_ops fh_gmac_ethtool_ops = {
+ .begin = gmac_check_if_running,
+ .get_drvinfo = gmac_ethtool_getdrvinfo,
+ .get_settings = gmac_ethtool_getsettings,
+ .set_settings = gmac_ethtool_setsettings,
+ .get_msglevel = gmac_ethtool_getmsglevel,
+ .set_msglevel = gmac_ethtool_setmsglevel,
+ .get_regs = gmac_ethtool_gregs,
+ .get_regs_len = gmac_ethtool_get_regs_len,
+ .get_link = ethtool_op_get_link,
+ .get_pauseparam = gmac_get_pauseparam,
+ .set_pauseparam = gmac_set_pauseparam,
+ .get_ethtool_stats = gmac_get_ethtool_stats,
+ .get_strings = gmac_get_strings,
+ .get_wol = gmac_get_wol,
+ .set_wol = gmac_set_wol,
+ .get_sset_count = gmac_get_sset_count,
+};
+
+void fh_gmac_set_ethtool_ops(struct net_device *netdev)
+{
+ netdev->ethtool_ops = &fh_gmac_ethtool_ops;
+}
diff --git a/drivers/net/ethernet/fullhan/fh_gmac_main.c b/drivers/net/ethernet/fullhan/fh_gmac_main.c
new file mode 100644
index 00000000..5c0cd48d
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/fh_gmac_main.c
@@ -0,0 +1,1300 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/highmem.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/phy.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/irqreturn.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <linux/crc32.h>
+#include <mach/pmu.h>
+#include "fh_gmac.h"
+#include <linux/gpio.h>
+#include <mach/fh_gmac_plat.h>
+/* Module parameters */
+static int watchdog = TX_TIMEO;
+static int debug = 16; /* -1: default, 0: no output, 16: all */
+static int dma_txsize = DMA_TX_SIZE;
+static int dma_rxsize = DMA_RX_SIZE;
+static int flow_ctrl = FLOW_AUTO;
+static int pause = PAUSE_TIME;
+
+static unsigned int phymode = PHY_INTERFACE_MODE_RMII;
+extern int auto_find_phy(Gmac_Object* gmac);
+
+#if defined(FH_GMAC_XMIT_DEBUG) || defined(FH_GMAC_RX_DEBUG)
+static void print_pkt(unsigned char *buf, int len)
+{
+ int j;
+
+ printk(KERN_DEBUG "len = %d byte, buf addr: 0x%p", len, buf);
+ for (j = 0; j < len; j++) {
+ if ((j % 16) == 0)
+ printk("\n %03x:", j);
+ printk(KERN_DEBUG " %02x", buf[j]);
+ }
+ printk(KERN_DEBUG "\n");
+}
+#endif
+
+static __u32 GMAC_BitReverse(register __u32 x)
+{
+ register __u32 y = 0x55555555;
+ x = (((x >> 1) & y) | ((x & y) << 1));
+ y = 0x33333333;
+ x = (((x >> 2) & y) | ((x & y) << 2));
+ y = 0x0f0f0f0f;
+ x = (((x >> 4) & y) | ((x & y) << 4));
+ y = 0x00ff00ff;
+ x = (((x >> 8) & y) | ((x & y) << 8));
+ return((x >> 16) | (x << 16));
+}
+
+static void fh_gmac_plat_init(void)
+{
+ fh_pmu_eth_set_speed(100);
+ fh_pmu_eth_reset();
+}
+
+static void fh_gmac_set_rmii_speed(Gmac_Object *pGmac, int speed)
+{
+ fh_pmu_eth_set_speed(speed);
+}
+
+static void GMAC_SetMacAddress(Gmac_Object* pGmac)
+{
+
+ __u32 macHigh = pGmac->local_mac_address[5]<<8 | pGmac->local_mac_address[4];
+ __u32 macLow = pGmac->local_mac_address[3]<<24 | pGmac->local_mac_address[2]<<16 | pGmac->local_mac_address[1]<<8 | pGmac->local_mac_address[0];
+
+ writel(macHigh, pGmac->remap_addr + REG_GMAC_MAC_HIGH);
+ writel(macLow, pGmac->remap_addr + REG_GMAC_MAC_LOW);
+}
+
+int gmac_dev_set_mac_addr(struct net_device *dev, void *p)
+{
+ Gmac_Object *pGmac = netdev_priv(dev);
+ struct sockaddr *addr = p;
+ memcpy(pGmac->local_mac_address, addr->sa_data, ETH_ALEN);
+ GMAC_SetMacAddress(pGmac);
+ return eth_mac_addr(dev, p);
+}
+
+static inline void GMAC_EnableMac(Gmac_Object* pGmac)
+{
+ /* transmitter enable */
+ /* receive enable */
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_CONFIG);
+ reg |= 0xc;
+ writel(reg, pGmac->remap_addr + REG_GMAC_CONFIG);
+}
+
+
+
+static inline void GMAC_DisableMac(Gmac_Object* pGmac)
+{
+ /* transmitter disable */
+ /* receive disable */
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_CONFIG);
+ reg &= ~0xc;
+ writel(reg | 0xc, pGmac->remap_addr + REG_GMAC_CONFIG);
+}
+
+static inline void GMAC_CoreInit(Gmac_Object* pGmac)
+{
+ //FIXME: heartbeat disable
+ //auto pad or crc stripping
+ __u32 reg = readl(pGmac->remap_addr + REG_GMAC_CONFIG);
+ reg |= 0x80;
+ writel(reg | 0xc, pGmac->remap_addr + REG_GMAC_CONFIG);
+}
+
+void GMAC_FlowCtrl(Gmac_Object* pGmac, unsigned int duplex,
+ unsigned int fc, unsigned int pause_time)
+{
+ __u32 flow = fc;
+
+ if (duplex)
+ flow |= (pause_time << 16);
+ writel(flow, pGmac->remap_addr + REG_GMAC_FLOW_CTRL);
+}
+
+void GMAC_IsrSet(Gmac_Object* pGmac, unsigned int isr)
+{
+ writel(isr, pGmac->remap_addr + REG_GMAC_INTR_EN);
+}
+
+static void gmac_tx_err(Gmac_Object* pGmac)
+{
+
+ netif_stop_queue(pGmac->ndev);
+ GMAC_DMA_StopTx(pGmac);
+ GMAC_DMA_FreeTxSkbufs(pGmac);
+ GMAC_DMA_InitTxDesc(pGmac->tx_dma_descriptors, pGmac->dma_tx_size);
+ pGmac->dirty_tx = 0;
+ pGmac->cur_tx = 0;
+ GMAC_DMA_StartTx(pGmac);
+ pGmac->ndev->stats.tx_errors++;
+ netif_wake_queue(pGmac->ndev);
+}
+
+
+static irqreturn_t fh_gmac_interrupt(int irq, void *dev_id)
+{
+
+ struct net_device *ndev = (struct net_device *)dev_id;
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ int status;
+
+ if (unlikely(!ndev))
+ {
+ pr_err("%s: invalid ndev pointer\n", __func__);
+ return IRQ_NONE;
+ }
+
+
+ status = GMAC_DMA_Interrupt(pGmac);
+ if (likely(status == handle_tx_rx))
+ {
+ if (likely(napi_schedule_prep(&pGmac->napi)))
+ {
+ GMAC_IsrSet(pGmac, 0);
+ __napi_schedule(&pGmac->napi);
+ }
+ }
+ else if (unlikely(status & tx_hard_error_bump_tc))
+ {
+ //FIXME: tx underflow
+ }
+ else if (unlikely(status == tx_hard_error))
+ {
+ gmac_tx_err(pGmac);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void fh_gmac_verify_args(void)
+{
+ if (unlikely(watchdog < 0))
+ watchdog = TX_TIMEO;
+ if (unlikely(dma_rxsize < 0))
+ dma_rxsize = DMA_RX_SIZE;
+ if (unlikely(dma_txsize < 0))
+ dma_txsize = DMA_TX_SIZE;
+ if (unlikely(flow_ctrl > 1))
+ flow_ctrl = FLOW_AUTO;
+ else if (likely(flow_ctrl < 0))
+ flow_ctrl = FLOW_OFF;
+ if (unlikely((pause < 0) || (pause > 0xffff)))
+ pause = PAUSE_TIME;
+
+}
+
+static void fh_gmac_adjust_link(struct net_device *ndev)
+{
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ struct phy_device *phydev = pGmac->phydev;
+ unsigned long flags;
+ int new_state = 0;
+
+ if (phydev == NULL)
+ return;
+
+ spin_lock_irqsave(&pGmac->lock, flags);
+ if (phydev->link)
+ {
+ __u32 ctrl = readl(pGmac->remap_addr + REG_GMAC_CONFIG);
+
+ /* Now we make sure that we can be in full duplex mode.
+ * If not, we operate in half-duplex mode. */
+ if (phydev->duplex != pGmac->oldduplex)
+ {
+ new_state = 1;
+ if (!(phydev->duplex))
+ ctrl &= ~0x800;
+ else
+ ctrl |= 0x800;
+ pGmac->oldduplex = phydev->duplex;
+ }
+ /* Flow Control operation */
+ if (phydev->pause)
+ {
+ __u32 fc = pGmac->flow_ctrl, pause_time = pGmac->pause;
+ GMAC_FlowCtrl(pGmac, phydev->duplex, fc, pause_time);
+ }
+
+ if (phydev->speed != pGmac->speed)
+ {
+ new_state = 1;
+ switch (phydev->speed)
+ {
+ case 100:
+ ctrl |= 0x4000;
+ fh_gmac_set_rmii_speed(pGmac, phydev->speed);
+ break;
+ case 10:
+ ctrl &= ~0x4000;
+ fh_gmac_set_rmii_speed(pGmac, phydev->speed);
+ break;
+ default:
+ if (netif_msg_link(pGmac))
+ pr_warning("%s: Speed (%d) is not 10"
+ " or 100!\n", ndev->name, phydev->speed);
+ break;
+ }
+
+ pGmac->speed = phydev->speed;
+ }
+ writel(ctrl, pGmac->remap_addr + REG_GMAC_CONFIG);
+ if (!pGmac->oldlink)
+ {
+ new_state = 1;
+ pGmac->oldlink = 1;
+ }
+ }
+ else if (pGmac->oldlink)
+ {
+ new_state = 1;
+ pGmac->oldlink = 0;
+ pGmac->speed = 0;
+ pGmac->oldduplex = -1;
+ }
+
+ if (new_state && netif_msg_link(pGmac))
+ phy_print_status(phydev);
+
+ spin_unlock_irqrestore(&pGmac->lock, flags);
+}
+
+
+static inline void fh_gmac_rx_refill(Gmac_Object* pGmac)
+{
+ __u32 rxsize = pGmac->dma_rx_size;
+ int bfsize = pGmac->dma_buf_sz;
+ Gmac_Rx_DMA_Descriptors *desc = pGmac->rx_dma_descriptors;
+
+ for (; pGmac->cur_rx - pGmac->dirty_rx > 0; pGmac->dirty_rx++)
+ {
+ __u32 entry = pGmac->dirty_rx % rxsize;
+ if (likely(pGmac->rx_skbuff[entry] == NULL))
+ {
+ struct sk_buff *skb;
+
+ skb = __skb_dequeue(&pGmac->rx_recycle);
+ if (skb == NULL)
+ skb = netdev_alloc_skb_ip_align(pGmac->ndev, bfsize);
+
+ if (unlikely(skb == NULL))
+ break;
+
+ pGmac->rx_skbuff[entry] = skb;
+ pGmac->rx_skbuff_dma[entry] =
+ dma_map_single(pGmac->dev, skb->data, bfsize,
+ DMA_FROM_DEVICE);
+
+ (desc + entry)->desc2.dw = pGmac->rx_skbuff_dma[entry];
+ RX_DBG(KERN_INFO "\trefill entry #%d\n", entry);
+ }
+ wmb();
+ (desc+entry)->desc0.bit.own = 1;
+ wmb();
+ }
+}
+
+static int fh_gmac_rx(Gmac_Object* pGmac, int limit)
+{
+ __u32 rxsize = pGmac->dma_rx_size;
+ __u32 entry = pGmac->cur_rx % rxsize;
+ __u32 next_entry;
+ __u32 count = 0;
+ Gmac_Rx_DMA_Descriptors *desc = pGmac->rx_dma_descriptors + entry;
+ Gmac_Rx_DMA_Descriptors *desc_next;
+
+#ifdef FH_GMAC_RX_DEBUG
+ if (netif_msg_hw(pGmac))
+ {
+ printk(">>> fh_gmac_rx: descriptor ring:\n");
+ GMAC_DMA_DisplayRxDesc(pGmac->rx_dma_descriptors, rxsize);
+ }
+#endif
+ count = 0;
+ while (!desc->desc0.bit.own)
+ {
+ int status;
+
+ if (count >= limit)
+ break;
+
+ count++;
+
+ next_entry = (++pGmac->cur_rx) % rxsize;
+ desc_next = pGmac->rx_dma_descriptors + next_entry;
+ prefetch(desc_next);
+
+ /* read the status of the incoming frame */
+ status = (GMAC_DMA_RxStatus(pGmac, desc));
+ if (unlikely(status == discard_frame))
+ {
+ pGmac->ndev->stats.rx_errors++;
+ }
+ else
+ {
+ struct sk_buff *skb;
+ int frame_len;
+ frame_len = desc->desc0.bit.frame_length;
+ /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
+ * Type frames (LLC/LLC-SNAP) */
+ if (unlikely(status != llc_snap))
+ frame_len -= ETH_FCS_LEN;
+#ifdef FH_GMAC_RX_DEBUG
+ if (frame_len > ETH_FRAME_LEN)
+ pr_debug("\tRX frame size %d, COE status: %d\n",
+ frame_len, status);
+
+ if (netif_msg_hw(pGmac))
+ pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
+ desc, entry, desc->desc2.dw);
+#endif
+ skb = pGmac->rx_skbuff[entry];
+ if (unlikely(!skb))
+ {
+ pr_err("%s: Inconsistent Rx descriptor chain\n",
+ pGmac->ndev->name);
+ pGmac->ndev->stats.rx_dropped++;
+ break;
+ }
+ prefetch(skb->data - NET_IP_ALIGN);
+ pGmac->rx_skbuff[entry] = NULL;
+
+ skb_put(skb, frame_len);
+ dma_unmap_single(pGmac->dev,
+ pGmac->rx_skbuff_dma[entry],
+ pGmac->dma_buf_sz, DMA_FROM_DEVICE);
+#ifdef FH_GMAC_RX_DEBUG
+ if (netif_msg_pktdata(pGmac))
+ {
+ pr_info(" frame received (%dbytes)", frame_len);
+ print_pkt(skb->data, frame_len);
+ }
+#endif
+ skb->protocol = eth_type_trans(skb, pGmac->ndev);
+
+ if (unlikely(status == csum_none))
+ {
+ /* always for the old mac 10/100 */
+ skb_checksum_none_assert(skb);
+ netif_receive_skb(skb);
+ }
+ else
+ {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ napi_gro_receive(&pGmac->napi, skb);
+ }
+
+ pGmac->ndev->stats.rx_packets++;
+ pGmac->ndev->stats.rx_bytes += frame_len;
+ }
+ entry = next_entry;
+ desc = desc_next; /* use prefetched values */
+ }
+
+ fh_gmac_rx_refill(pGmac);
+
+ pGmac->stats.rx_pkt_n += count;
+
+ return count;
+}
+
+/* minimum number of free TX descriptors required to wake up TX process */
+#define FH_GMAC_TX_THRESH(x) (x->dma_tx_size/4)
+
+static inline __u32 gmac_tx_avail(Gmac_Object* pGmac)
+{
+ return pGmac->dirty_tx + pGmac->dma_tx_size - pGmac->cur_tx - 1;
+}
+
+
+
+static void fh_gmac_tx(Gmac_Object* pGmac)
+{
+ __u32 txsize = pGmac->dma_tx_size;
+
+ while (pGmac->dirty_tx != pGmac->cur_tx)
+ {
+ int last;
+ __u32 entry = pGmac->dirty_tx % txsize;
+ struct sk_buff *skb = pGmac->tx_skbuff[entry];
+ Gmac_Tx_DMA_Descriptors *desc = pGmac->tx_dma_descriptors + entry;
+
+ /* Check if the descriptor is owned by the DMA. */
+ if (desc->desc0.bit.own)
+ break;
+
+ /* Verify tx error by looking at the last segment */
+ last = desc->desc1.bit.last_segment;
+ if (likely(last))
+ {
+ int tx_error = GMAC_DMA_TxStatus(pGmac, desc);
+ if (likely(tx_error == 0))
+ {
+ pGmac->ndev->stats.tx_packets++;
+ pGmac->stats.tx_pkt_n++;
+ }
+ else
+ {
+ pGmac->ndev->stats.tx_errors++;
+ }
+ }
+ TX_DBG("%s: curr %d, dirty %d\n", __func__,
+ pGmac->cur_tx, pGmac->dirty_tx);
+
+ if (likely(desc->desc2.dw))
+ {
+ dma_unmap_single(pGmac->dev, desc->desc2.dw, desc->desc1.bit.buffer1_size,
+ DMA_TO_DEVICE);
+ }
+ if (unlikely(desc->desc3.dw))
+ {
+ desc->desc3.dw = 0;
+ }
+
+ if (likely(skb != NULL))
+ {
+ dev_consume_skb_any(skb);
+ pGmac->tx_skbuff[entry] = NULL;
+ }
+ GMAC_DMA_ReleaseTxDesc(desc);
+
+ entry = (++pGmac->dirty_tx) % txsize;
+ }
+ if (unlikely(netif_queue_stopped(pGmac->ndev) &&
+ gmac_tx_avail(pGmac) > FH_GMAC_TX_THRESH(pGmac)))
+ {
+ netif_tx_lock(pGmac->ndev);
+ if (netif_queue_stopped(pGmac->ndev) &&
+ gmac_tx_avail(pGmac) > FH_GMAC_TX_THRESH(pGmac))
+ {
+ TX_DBG("%s: restart transmit\n", __func__);
+ netif_wake_queue(pGmac->ndev);
+ }
+ netif_tx_unlock(pGmac->ndev);
+ }
+
+}
+
+
+static int fh_gmac_poll(struct napi_struct *napi, int budget)
+{
+ Gmac_Object* pGmac = container_of(napi, Gmac_Object, napi);
+ int work_done = 0;
+
+ pGmac->stats.poll_n++;
+ fh_gmac_tx(pGmac);
+ work_done = fh_gmac_rx(pGmac, budget);
+
+ if (work_done < budget)
+ {
+ napi_complete(napi);
+ GMAC_IsrSet(pGmac, 0x1a061);
+ }
+ return work_done;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/* Polling receive - used by NETCONSOLE and other diagnostic tools
+ * to allow network I/O with interrupts disabled. */
+static void gmac_poll_controller(struct net_device *ndev)
+{
+ disable_irq(ndev->irq);
+ fh_gmac_interrupt(ndev->irq, ndev);
+ enable_irq(ndev->irq);
+}
+#endif
+
+
+static __u32 gmac_handle_jumbo_frames(struct sk_buff *skb, struct net_device *dev, int checksum_insertion)
+{
+ //FIXME: 8K jumbo frame
+ Gmac_Object* pGmac = netdev_priv(dev);
+ __u32 nopaged_len = skb_headlen(skb);
+ __u32 txsize = pGmac->dma_tx_size;
+ __u32 entry = pGmac->cur_tx % txsize;
+ Gmac_Tx_DMA_Descriptors *desc = pGmac->tx_dma_descriptors + entry;
+
+ if (nopaged_len > BUFFER_SIZE_2K)
+ {
+
+ int buf2_size = nopaged_len - BUFFER_SIZE_2K + 1;
+
+ desc->desc2.dw = dma_map_single(pGmac->dev, skb->data,
+ BUFFER_SIZE_2K, DMA_TO_DEVICE);
+ desc->desc3.dw = desc->desc2.dw + BUFFER_SIZE_2K;
+ desc->desc1.bit.first_segment = 1;
+ desc->desc1.bit.buffer1_size = BUFFER_SIZE_2K - 1;
+ desc->desc1.bit.checksum_insertion_ctrl = 3;
+ entry = (++pGmac->cur_tx) % txsize;
+ desc = pGmac->tx_dma_descriptors + entry;
+ desc->desc2.dw = dma_map_single(pGmac->dev,
+ skb->data + BUFFER_SIZE_2K,
+ buf2_size, DMA_TO_DEVICE);
+ desc->desc3.dw = desc->desc2.dw + BUFFER_SIZE_2K;
+ desc->desc1.bit.first_segment = 0;
+ desc->desc1.bit.buffer1_size = buf2_size;
+ desc->desc1.bit.checksum_insertion_ctrl = checksum_insertion;
+ desc->desc0.bit.own = 1;
+ pGmac->tx_skbuff[entry] = NULL;
+ }
+ else
+ {
+ desc->desc2.dw = dma_map_single(pGmac->dev, skb->data,
+ nopaged_len, DMA_TO_DEVICE);
+ desc->desc3.dw = desc->desc2.dw + BUFFER_SIZE_2K;
+ desc->desc1.bit.first_segment = 1;
+ desc->desc1.bit.buffer1_size = nopaged_len;
+ desc->desc1.bit.checksum_insertion_ctrl = checksum_insertion;
+ }
+ return entry;
+}
+
+/* Configuration changes (passed on by ifconfig) */
+static int gmac_dev_set_config(struct net_device *ndev, struct ifmap *map)
+{
+ if (ndev->flags & IFF_UP) /* can't act on a running interface */
+ return -EBUSY;
+
+ /* Don't allow changing the I/O address */
+ if (map->base_addr != ndev->base_addr) {
+ pr_warning("%s: can't change I/O address\n", ndev->name);
+ return -EOPNOTSUPP;
+ }
+
+ /* Don't allow changing the IRQ */
+ if (map->irq != ndev->irq) {
+ pr_warning("%s: can't change IRQ number %d\n",
+ ndev->name, ndev->irq);
+ return -EOPNOTSUPP;
+ }
+
+ /* ignore other fields */
+ return 0;
+}
+
+
+static int gmac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ __u32 txsize = pGmac->dma_tx_size;
+ __u32 entry;
+ int i, csum_insertion = 0;
+ int nfrags = skb_shinfo(skb)->nr_frags;
+ Gmac_Tx_DMA_Descriptors *desc, *first;
+
+ if (unlikely(gmac_tx_avail(pGmac) < nfrags + 1))
+ {
+
+ if (!netif_queue_stopped(ndev))
+ {
+ netif_stop_queue(ndev);
+ /* This is a hard error, log it. */
+ pr_err("%s: BUG! Tx Ring full when queue awake\n",
+ __func__);
+ }
+ return NETDEV_TX_BUSY;
+ }
+
+ entry = pGmac->cur_tx % txsize;
+ //fixme: debug
+
+#ifdef FH_GMAC_XMIT_DEBUG
+ if ((skb->len > ETH_FRAME_LEN) || nfrags)
+ pr_info("fh gmac xmit:\n"
+ "\tskb addr %p - len: %d - nopaged_len: %d\n"
+ "\tn_frags: %d - ip_summed: %d - %s gso\n",
+ skb, skb->len, skb_headlen(skb), nfrags,
+ skb->ip_summed,
+ !skb_is_gso(skb) ? "isn't" : "is");
+#endif
+
+ csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL)? 3 : 0;
+
+ desc = pGmac->tx_dma_descriptors + entry;
+ first = desc;
+
+#ifdef FH_GMAC_XMIT_DEBUG
+ if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN))
+ pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n"
+ "\t\tn_frags: %d, ip_summed: %d\n",
+ skb->len, skb_headlen(skb), nfrags, skb->ip_summed);
+#endif
+ pGmac->tx_skbuff[entry] = skb;
+ if (unlikely(skb->len >= BUFFER_SIZE_2K))
+ {
+ printk("jumbo_frames detected\n");
+ entry = gmac_handle_jumbo_frames(skb, ndev, csum_insertion);
+ desc = pGmac->tx_dma_descriptors + entry;
+ }
+ else
+ {
+ __u32 nopaged_len = skb_headlen(skb);
+
+ desc->desc2.dw = dma_map_single(pGmac->dev, skb->data,
+ nopaged_len, DMA_TO_DEVICE);
+ desc->desc1.bit.first_segment = 1;
+ desc->desc1.bit.buffer1_size = nopaged_len;
+ desc->desc1.bit.checksum_insertion_ctrl = csum_insertion;
+ }
+
+ for (i = 0; i < nfrags; i++)
+ {
+ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ int len = frag->size;
+
+ entry = (++pGmac->cur_tx) % txsize;
+ desc = pGmac->tx_dma_descriptors + entry;
+
+ TX_DBG("\t[entry %d] segment len: %d\n", entry, len);
+ desc->desc2.dw = skb_frag_dma_map(pGmac->dev, frag, 0, len,
+ DMA_TO_DEVICE);
+ pGmac->tx_skbuff[entry] = NULL;
+ desc->desc1.bit.first_segment = 0;
+ desc->desc1.bit.buffer1_size = len;
+ wmb();
+ desc->desc1.bit.checksum_insertion_ctrl = csum_insertion;
+ desc->desc0.bit.own = 1;
+ wmb();
+ }
+
+ /* Interrupt on completition only for the latest segment */
+ desc->desc1.bit.last_segment = 1;
+ desc->desc1.bit.intr_on_completion = 1;
+ wmb();
+
+ /* To avoid raise condition */
+ first->desc0.bit.own = 1;
+ wmb();
+ pGmac->cur_tx++;
+
+#ifdef FH_GMAC_XMIT_DEBUG
+ if (netif_msg_pktdata(pGmac)) {
+ pr_info("fh gmac xmit: current=%d, dirty=%d, entry=%d, "
+ "first=%p, nfrags=%d\n",
+ (pGmac->cur_tx % txsize), (pGmac->dirty_tx % txsize),
+ entry, first, nfrags);
+ GMAC_DMA_DisplayTxDesc(pGmac->tx_dma_descriptors, 3);
+ pr_info(">>> frame to be transmitted: ");
+ print_pkt(skb->data, skb->len);
+ }
+#endif
+ if (unlikely(gmac_tx_avail(pGmac) <= (MAX_SKB_FRAGS + 1)))
+ {
+ TX_DBG("%s: stop transmitted packets\n", __func__);
+ netif_stop_queue(ndev);
+ }
+
+ ndev->stats.tx_bytes += skb->len;
+ writel(0x1, pGmac->remap_addr + REG_GMAC_TX_POLL_DEMAND);
+
+ return NETDEV_TX_OK;
+}
+
+static void gmac_dev_tx_timeout(struct net_device *ndev)
+{
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ gmac_tx_err(pGmac);
+}
+
+static int gmac_dev_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ int max_mtu;
+
+ if (netif_running(ndev))
+ {
+ pr_err("%s: must be stopped to change its MTU\n", ndev->name);
+ return -EBUSY;
+ }
+
+ max_mtu = ETH_DATA_LEN;
+
+ if ((new_mtu < 46) || (new_mtu > max_mtu))
+ {
+ pr_err("%s: invalid MTU, max MTU is: %d\n",
+ ndev->name, max_mtu);
+ return -EINVAL;
+ }
+
+ ndev->mtu = new_mtu;
+ netdev_update_features(ndev);
+
+ return 0;
+}
+
+static void gmac_set_filter(struct net_device *ndev)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ __u32 value = readl(pGmac->remap_addr + REG_GMAC_FRAME_FILTER);
+
+ if (ndev->flags & IFF_PROMISC)
+ {
+ //enable Promiscuous Mode
+ value = 0x1;
+ }
+ else if ((netdev_mc_count(ndev) > 64) //HASH_TABLE_SIZE = 64
+ || (ndev->flags & IFF_ALLMULTI))
+ {
+ //enable Pass All Multicast
+ value = 0x10;
+
+ writel(0xffffffff, pGmac->remap_addr + REG_GMAC_HASH_HIGH);
+ writel(0xffffffff, pGmac->remap_addr + REG_GMAC_HASH_LOW);
+ }
+ else if (netdev_mc_empty(ndev))
+ { /* no multicast */
+ value = 0;
+ }
+ else
+ {
+ __u32 mc_filter[2];
+ struct netdev_hw_addr *ha;
+
+ /* Perfect filter mode for physical address and Hash
+ filter for multicast */
+ value = 0x404;
+
+ memset(mc_filter, 0, sizeof(mc_filter));
+ netdev_for_each_mc_addr(ha, ndev)
+ {
+ /* The upper 6 bits of the calculated CRC are used to
+ * index the contens of the hash table */
+ int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
+
+ /* The most significant bit determines the register to
+ * use (H/L) while the other 5 bits determine the bit
+ * within the register. */
+ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+ }
+ writel(GMAC_BitReverse(mc_filter[0]),
+ pGmac->remap_addr + REG_GMAC_HASH_HIGH);
+ writel(GMAC_BitReverse(mc_filter[1]),
+ pGmac->remap_addr + REG_GMAC_HASH_LOW);
+ }
+ writel(value, pGmac->remap_addr + REG_GMAC_FRAME_FILTER);
+}
+
+static void gmac_dev_mcast_set(struct net_device *ndev)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+
+ spin_lock(&pGmac->lock);
+ gmac_set_filter(ndev);
+ spin_unlock(&pGmac->lock);
+}
+
+static int gmac_dev_ioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
+{
+ Gmac_Object* pGmac = netdev_priv(ndev);
+ int ret;
+
+ if (!netif_running(ndev))
+ return -EINVAL;
+
+ if (!pGmac->phydev)
+ return -EINVAL;
+
+ ret = phy_mii_ioctl(pGmac->phydev, ifrq, cmd);
+
+ return ret;
+
+}
+
+static int fh_gmac_init_phy(struct net_device *ndev)
+{
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ struct phy_device *phydev;
+ char phy_id[MII_BUS_ID_SIZE + 3];
+ char bus_id[MII_BUS_ID_SIZE];
+
+ if (pGmac->phydev == NULL)
+ return -ENODEV;
+
+ snprintf(bus_id, MII_BUS_ID_SIZE, "%x", 0);
+ snprintf(phy_id, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, pGmac->phyid);
+ pr_debug("fh_gmac_init_phy: trying to attach to %s\n", phy_id);
+
+ phydev = phy_connect(ndev, phy_id, &fh_gmac_adjust_link,
+ pGmac->phy_interface);
+ if (IS_ERR(phydev))
+ {
+ pr_err("%s: Could not attach to PHY\n", ndev->name);
+ return PTR_ERR(phydev);
+ }
+
+ phydev->advertising &=
+ ~(SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full);
+
+
+ //FIXME: phy_id == 0
+ /*
+ * Broken HW is sometimes missing the pull-up resistor on the
+ * MDIO line, which results in reads to non-existent devices returning
+ * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
+ * device as well.
+ * Note: phydev->phy_id is the result of reading the UID PHY registers.
+ */
+ if (phydev->phy_id == 0)
+ {
+ phy_disconnect(phydev);
+ return -ENODEV;
+ }
+ pr_debug("fh_gmac_init_phy: %s: attached to PHY (UID 0x%x)"
+ " Link = %d\n", ndev->name, phydev->phy_id, phydev->link);
+
+ return 0;
+}
+
+
+static int gmac_dev_open(struct net_device *ndev)
+{
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ bind_no_link_process(pGmac->phydev->drv, fh_phy_reset_api);
+ phy_start(pGmac->phydev);
+ GMAC_DMA_StartTx(pGmac);
+ GMAC_DMA_StartRx(pGmac);
+ //ndev->operstate = IF_OPER_UP;
+ napi_enable(&pGmac->napi);
+ skb_queue_head_init(&pGmac->rx_recycle);
+ netif_start_queue(ndev);
+ GMAC_IsrSet(pGmac, 0x1a061);
+ return 0;
+}
+
+static int gmac_dev_stop(struct net_device *ndev)
+{
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ GMAC_IsrSet(pGmac, 0);
+ phy_stop(pGmac->phydev);
+ netif_stop_queue(ndev);
+ napi_disable(&pGmac->napi);
+ skb_queue_purge(&pGmac->rx_recycle);
+ /* Stop TX/RX DMA and clear the descriptors */
+ GMAC_DMA_StopTx(pGmac);
+ GMAC_DMA_StopRx(pGmac);
+ netif_carrier_off(ndev);
+ return 0;
+}
+
+
+static const struct net_device_ops fh_gmac_netdev_ops =
+{
+ .ndo_open = gmac_dev_open,
+ .ndo_stop = gmac_dev_stop,
+ .ndo_start_xmit = gmac_dev_xmit,
+ .ndo_set_rx_mode = gmac_dev_mcast_set,
+ .ndo_set_mac_address = gmac_dev_set_mac_addr,
+ .ndo_do_ioctl = gmac_dev_ioctl,
+ .ndo_tx_timeout = gmac_dev_tx_timeout,
+ .ndo_change_mtu = gmac_dev_change_mtu,
+ .ndo_fix_features = NULL,
+ .ndo_set_config = gmac_dev_set_config,
+#ifdef STMMAC_VLAN_TAG_USED
+ .ndo_vlan_rx_register = stmmac_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = gmac_poll_controller,
+#endif
+};
+
+static int fh_gmac_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ Gmac_Object *pGmac;
+ struct clk *rmii_clk;
+ struct net_device *ndev;
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *regs;
+ struct fh_gmac_platform_data *p_plat_data;
+#endif
+
+ pr_info("GMAC driver:\n\tplatform registration... ");
+
+ ndev = alloc_etherdev(sizeof(Gmac_Object));
+ if (!ndev)
+ {
+ pr_err("%s: ERROR: allocating the device\n", __func__);
+ ret = -ENOMEM;
+ goto out_free_ndev;
+ }
+ pGmac = netdev_priv(ndev);
+
+#ifdef CONFIG_USE_OF
+ ndev->irq = irq_of_parse_and_map(np, 0);
+ if (!ndev->irq)
+ {
+ pr_err("%s: ERROR: getting resource failed"
+ "cannot get IORESOURCE_IRQ\n", __func__);
+ ret = -ENXIO;
+ goto out_free_ndev;
+ }
+
+ /* fill in parameters for net-dev structure */
+
+ pGmac->remap_addr = of_iomap(np, 0);
+ if (!pGmac->remap_addr) {
+ pr_err("%s: ERROR: memory mapping failed\n", __func__);
+ ret = -ENOMEM;
+ goto out_free_ndev;
+ }
+
+ ndev->base_addr = (unsigned long)pGmac->remap_addr;
+
+ of_property_read_u32(np, "phyreset-gpio",
+ &pGmac->phyreset_gpio);
+
+#else
+
+ p_plat_data = (struct fh_gmac_platform_data *)pdev->dev.platform_data;
+ ndev->irq = platform_get_irq(pdev, 0);
+ ndev->irq = irq_create_mapping(NULL, ndev->irq);
+
+ if (!ndev->irq) {
+ pr_err("%s: ERROR: getting resource failed"
+ "cannot get IORESOURCE_IRQ\n", __func__);
+ ret = -ENXIO;
+ goto out_free_ndev;
+ }
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ pr_err("%s: ERROR: no resource\n", __func__);
+ ret = -ENOMEM;
+ goto out_free_ndev;
+ }
+
+ pGmac->remap_addr = ioremap_nocache(regs->start,
+ regs->end - regs->start + 1);
+ if (!pGmac->remap_addr) {
+ pr_err("%s: ERROR: memory mapping failed\n", __func__);
+ ret = -ENOMEM;
+ goto out_free_ndev;
+ }
+ ndev->base_addr = (unsigned long)pGmac->remap_addr;
+ pGmac->phyreset_gpio = p_plat_data->phy_reset_pin;
+#endif /* end CONFIG_USE_OF */
+
+ pGmac->clk = clk_get(&pdev->dev, "eth_clk");
+ if (IS_ERR(pGmac->clk)) {
+ ret = PTR_ERR(pGmac->clk);
+ goto out_unmap;
+ }
+
+ clk_prepare_enable(pGmac->clk);
+
+ rmii_clk = clk_get(&pdev->dev, "eth_rmii_clk");
+ if (!IS_ERR(rmii_clk))
+ clk_prepare_enable(rmii_clk);
+
+ /* add net_device to platform_device */
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ pGmac->dev = &(pdev->dev);
+ pGmac->pdev = pdev;
+ pGmac->ndev = ndev;
+
+ platform_set_drvdata(pdev, ndev);
+ ndev->base_addr = (unsigned long)pGmac->remap_addr;
+
+ ether_setup(ndev);
+ ndev->netdev_ops = &fh_gmac_netdev_ops;
+ fh_gmac_set_ethtool_ops(ndev);
+
+ ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
+ NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+ ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+ ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+ pGmac->msg_enable = netif_msg_init(debug, FH_GMAC_DEBUG);
+ if (flow_ctrl)
+ pGmac->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */
+ pGmac->pause = pause;
+ netif_napi_add(ndev, &(pGmac->napi), fh_gmac_poll, NAPI_POLL_WEIGHT);
+ if (!is_valid_ether_addr(pGmac->local_mac_address)) {
+ /* Use random MAC if none passed */
+ random_ether_addr(pGmac->local_mac_address);
+ pr_warning("\tusing random MAC address: %pM\n",
+ pGmac->local_mac_address);
+ }
+ ndev->dev_addr = pGmac->local_mac_address;
+
+ if (auto_find_phy(pGmac))
+ pr_err("find no phy !!!!!!!");
+
+ spin_lock_init(&pGmac->lock);
+ /* Carrier starts down, phylib will bring it up */
+ netif_carrier_off(ndev);
+ ret = register_netdev(ndev);
+ if (ret) {
+ pr_err("%s: ERROR %i registering the netdevice\n", __func__, ret);
+ ret = -ENODEV;
+ goto out_plat_exit;
+ }
+
+ pr_info("\t%s - (dev. name: %s - id: %d, IRQ #%d\n"
+ "\t\tIO base addr: 0x%p)\n", ndev->name, pdev->name,
+ pdev->id, ndev->irq, pGmac->remap_addr);
+
+ pGmac->phy_interface = phymode;
+ /* MDIO bus Registration */
+ ret = fh_mdio_register(ndev);
+ if (ret < 0)
+ {
+ goto open_error;
+ }
+ fh_gmac_plat_init();
+ ret = fh_gmac_init_phy(ndev);
+ if (unlikely(ret)) {
+ pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
+ goto open_error;
+ }
+
+ fh_gmac_verify_args();
+ pGmac->dma_tx_size = dma_txsize;
+ pGmac->dma_rx_size = dma_rxsize;
+ pGmac->dma_buf_sz = BUFFER_SIZE_2K;
+ GMAC_DMA_InitDescRings(ndev);
+ /* Copy the MAC addr into the HW */
+ GMAC_SetMacAddress(pGmac);
+ /* Initialize the MAC Core */
+ GMAC_CoreInit(pGmac);
+ /* Request the IRQ lines */
+ ret = request_irq(ndev->irq, fh_gmac_interrupt, IRQF_SHARED, ndev->name, ndev);
+ if (unlikely(ret < 0)) {
+ pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
+ __func__, ndev->irq, ret);
+ goto open_error;
+ }
+ /* Enable the MAC Rx/Tx */
+ GMAC_EnableMac(pGmac);
+ /* Set the HW DMA mode and the COE */
+ GMAC_DMA_OpMode(pGmac);
+ /* Extra statistics */
+ memset(&pGmac->stats, 0, sizeof(struct Gmac_Stats));
+ pGmac->stats.threshold = 64;
+ GMAC_DMA_Init(ndev, pGmac->tx_bus_addr, pGmac->rx_bus_addr);
+ if (pGmac->phydev)
+ phy_start(pGmac->phydev);
+ return 0;
+
+open_error:
+ if (pGmac->phydev)
+ phy_disconnect(pGmac->phydev);
+out_plat_exit:
+
+ clk_disable_unprepare(pGmac->clk);
+ clk_put(pGmac->clk);
+out_unmap:
+ iounmap(pGmac->remap_addr);
+out_free_ndev:
+ unregister_netdev(ndev);
+ free_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+
+ return ret;
+}
+
+static int fh_gmac_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ struct resource *res;
+
+ pr_info("%s:\n\tremoving driver", __func__);
+ GMAC_DMA_StopTx(pGmac);
+ GMAC_DMA_StopRx(pGmac);
+ GMAC_DisableMac(pGmac);
+ netif_carrier_off(ndev);
+ GMAC_DMA_FreeDesc(pGmac);
+ platform_set_drvdata(pdev, NULL);
+ unregister_netdev(ndev);
+ free_irq(ndev->irq, ndev);
+ mdiobus_unregister(pGmac->mii);
+ mdiobus_free(pGmac->mii);
+ clk_disable_unprepare(pGmac->clk);
+ clk_put(pGmac->clk);
+ iounmap((void *)pGmac->remap_addr);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+ free_netdev(ndev);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int fh_gmac_suspend(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ if (!ndev || !netif_running(ndev))
+ return 0;
+
+ spin_lock(&pGmac->lock);
+
+ netif_device_detach(ndev);
+ netif_stop_queue(ndev);
+ if (pGmac->phydev)
+ phy_stop(pGmac->phydev);
+
+ napi_disable(&pGmac->napi);
+
+ /* Stop TX/RX DMA */
+ GMAC_DMA_StopTx(pGmac);
+ GMAC_DMA_StopRx(pGmac);
+ /* Clear the Rx/Tx descriptors */
+ GMAC_DMA_InitRxDesc(pGmac->rx_dma_descriptors, pGmac->dma_rx_size);
+ GMAC_DMA_InitTxDesc(pGmac->tx_dma_descriptors, pGmac->dma_tx_size);
+
+ /* Enable Power down mode by programming the PMT regs */
+ if (device_may_wakeup(pGmac->dev)) {
+ //priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
+ } else {
+ GMAC_DisableMac(pGmac);
+ }
+
+ spin_unlock(&pGmac->lock);
+ return 0;
+}
+
+static int fh_gmac_resume(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ u32 reg;
+
+ reg = pGmac->mii->read(pGmac->mii, 0, 0);
+ reg |= 1 << 15;
+ pGmac->mii->write(pGmac->mii, 0, 0, reg);
+
+ pGmac->mii->reset(pGmac->mii);
+
+ if (!netif_running(ndev))
+ return 0;
+
+ spin_lock(&pGmac->lock);
+
+ /* Power Down bit, into the PM register, is cleared
+ * automatically as soon as a magic packet or a Wake-up frame
+ * is received. Anyway, it's better to manually clear
+ * this bit because it can generate problems while resuming
+ * from another devices (e.g. serial console). */
+ if (device_may_wakeup(pGmac->dev)) {
+ //priv->hw->mac->pmt(priv->ioaddr, 0);
+ }
+
+ netif_device_attach(ndev);
+
+ /* Enable the MAC and DMA */
+ GMAC_EnableMac(pGmac);
+ GMAC_DMA_StartTx(pGmac);
+ GMAC_DMA_StartRx(pGmac);
+
+ napi_enable(&pGmac->napi);
+
+ if (pGmac->phydev)
+ phy_start(pGmac->phydev);
+
+ netif_start_queue(ndev);
+
+ spin_unlock(&pGmac->lock);
+ return 0;
+}
+
+static int fh_gmac_freeze(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ if (!ndev || !netif_running(ndev))
+ return 0;
+
+ return gmac_dev_stop(ndev);
+}
+
+static int fh_gmac_restore(struct device *dev)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ if (!ndev || !netif_running(ndev))
+ return 0;
+
+ return gmac_dev_open(ndev);
+}
+
+static const struct dev_pm_ops fh_gmac_pm_ops = {
+ .suspend = fh_gmac_suspend,
+ .resume = fh_gmac_resume,
+ .freeze = fh_gmac_freeze,
+ .thaw = fh_gmac_restore,
+ .restore = fh_gmac_restore,
+};
+#else
+static const struct dev_pm_ops fh_gmac_pm_ops;
+#endif /* CONFIG_PM */
+
+static const struct of_device_id fh_gmac_of_match[] = {
+ {.compatible = "fh,fh-gmac",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_gmac_of_match);
+
+static struct platform_driver fh_gmac_driver = {
+ .driver = {
+ .name = "fh_gmac",
+ .of_match_table = fh_gmac_of_match,
+ },
+ .probe = fh_gmac_probe,
+ .remove = fh_gmac_remove,
+};
+
+#ifdef CONFIG_DEFERRED_INIICALLS_GMAC
+deferred_module_platform_driver(fh_gmac_driver);
+#else
+module_platform_driver(fh_gmac_driver);
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("QIN");
+MODULE_DESCRIPTION("Fullhan Ethernet driver");
diff --git a/drivers/net/ethernet/fullhan/fh_gmac_phyt.c b/drivers/net/ethernet/fullhan/fh_gmac_phyt.c
new file mode 100644
index 00000000..07abfe97
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/fh_gmac_phyt.c
@@ -0,0 +1,514 @@
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include "fh_gmac_phyt.h"
+#include <mach/pmu.h>
+#include <mach/pinctrl.h>
+
+static int fh_gmac_ephy_reset(Gmac_Object *pGmac, __u32 phy_sel);
+static int fh_mdio_set_mii(struct mii_bus *bus);
+
+char *phy_driver_array[] = {
+ "Generic PHY",
+#if defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x)
+ "FH EPHY",
+#endif
+ 0,
+};
+#ifndef PHY_MAX_ADDR
+#define PHY_MAX_ADDR 32
+#endif
+
+struct mdio_pin_mux_ref {
+ char *old;
+ char *restore;
+};
+
+unsigned int phy_support_list[] = {
+ FH_GMAC_PHY_IP101G,
+ FH_GMAC_PHY_RTL8201,
+ FH_GMAC_PHY_TI83848,
+ FH_GMAC_PHY_INTERNAL,
+};
+
+struct mdio_pin_mux_ref _mdio_pin_ref_obj[] = {
+ {.old = "MAC_MDC", .restore = 0},
+ {.old = "MAC_MDIO", .restore = 0},
+ {.old = "MAC_RMII_CLK", .restore = 0},
+ {.old = "EX_PHY_RESET_PIN", .restore = 0},
+};
+
+void external_phy_pin_sel(Gmac_Object *gmac, int flag)
+{
+ int i;
+ char temp_buf[16] = {0};
+
+ if (flag) {
+ for (i = 0; i < ARRAY_SIZE(_mdio_pin_ref_obj); i++) {
+ if (strcmp(_mdio_pin_ref_obj[i].old,
+ "EX_PHY_RESET_PIN") == 0) {
+ sprintf(temp_buf,
+ "GPIO%d", gmac->phyreset_gpio);
+ _mdio_pin_ref_obj[i].restore =
+ fh_pinctrl_smux_backup(temp_buf, temp_buf, 0);
+ if (!_mdio_pin_ref_obj[i].restore)
+ pr_err("pin mux error!!!!\n");
+ } else {
+ _mdio_pin_ref_obj[i].restore =
+ fh_pinctrl_smux_backup("RMII",
+ _mdio_pin_ref_obj[i].old, 0);
+ if (!_mdio_pin_ref_obj[i].restore)
+ pr_err("pin mux error!!!!\n");
+ if (strcmp(_mdio_pin_ref_obj[i].old,
+ "MAC_RMII_CLK") == 0)
+ fh_pinctrl_smux("RMII",
+ "MAC_REF_CLK", 0, 0);
+ }
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(_mdio_pin_ref_obj); i++) {
+ if (!_mdio_pin_ref_obj[i].restore)
+ continue;
+ fh_pinctrl_smux_restore("RMII",
+ _mdio_pin_ref_obj[i].restore, 0);
+ if (strcmp(_mdio_pin_ref_obj[i].old,
+ "MAC_RMII_CLK") == 0)
+ fh_pinctrl_set_oe("MAC_REF_CLK", 0);
+ }
+ }
+}
+
+
+static int __fh_mdio_read(Gmac_Object *pGmac, int phyaddr, int phyreg)
+{
+ int ret;
+#ifdef CONFIG_EMULATION
+ return 0xe3ff;
+#else
+ int timeout = 1000;
+
+ if (phyaddr < 0)
+ return -ENODEV;
+
+ writel(phyaddr << 11 | gmac_gmii_clock_100_150 << 2 | phyreg << 6 | 0x1,
+ pGmac->remap_addr + REG_GMAC_GMII_ADDRESS);
+
+ while (readl(pGmac->remap_addr + REG_GMAC_GMII_ADDRESS) & 0x1) {
+ udelay(100);
+ timeout--;
+ if (timeout < 0) {
+ pr_err("ERROR: %s, timeout, phyaddr: 0x%x, phyreg: 0x%x\n",
+ __func__, phyaddr, phyreg);
+ break;
+ }
+ }
+ ret = readl(pGmac->remap_addr + REG_GMAC_GMII_DATA);
+ /*pr_err("add : reg : data = %x : %x : %x\n",phyaddr, phyreg, ret);*/
+ return ret;
+#endif
+}
+
+static int get_phy_id(Gmac_Object *gmac, int addr, u32 *phy_id)
+{
+ __u16 phy_reg;
+
+ phy_reg = __fh_mdio_read(gmac, addr, MII_PHYSID1);
+ *phy_id = (phy_reg & 0xffff) << 16;
+ phy_reg = __fh_mdio_read(gmac, addr, MII_PHYSID2);
+ *phy_id |= (phy_reg & 0xffff);
+
+ return 0;
+}
+
+
+int check_white_list(__u32 phy_id, __u32 *list, __u32 size)
+{
+ int i;
+ int ret = -1;
+
+ for (i = 0; i < size; i++) {
+ if (phy_id == list[i]) {
+ ret = 0;
+ break;
+ }
+ }
+ return ret;
+}
+
+/* 0 find vaild, others failed*/
+int scan_vaild_phy_id(Gmac_Object *gmac, __u32 *white_list, __u32 list_size)
+{
+ __u32 phy_id = 0;
+ int i;
+ int ret;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ ret = get_phy_id(gmac, i, &phy_id);
+ if (ret == 0 && (phy_id & 0x1fffffff) != 0x1fffffff) {
+ if (check_white_list(phy_id, white_list, list_size))
+ continue;
+ break;
+ }
+ }
+ if (i == PHY_MAX_ADDR)
+ return -1;
+
+ return 0;
+}
+
+
+int fh_phy_reset_api(struct phy_device *phydev)
+{
+ struct net_device *ndev;
+ Gmac_Object *pGmac;
+
+ ndev = phydev->mdio.bus->priv;
+ pGmac = netdev_priv(ndev);
+ fh_pmu_ephy_sel(pGmac->phy_sel);
+ fh_gmac_ephy_reset(pGmac, pGmac->phy_sel);
+ fh_mdio_set_mii(pGmac->mii);
+ return 0;
+
+}
+EXPORT_SYMBOL(fh_phy_reset_api);
+
+int auto_find_phy(Gmac_Object *gmac)
+{
+ int i;
+ int switch_flag = 0;
+ char *c_driver;
+ int ret;
+#ifdef CONFIG_EMULATION
+ gmac->phy_sel = EXTERNAL_PHY;
+ return 0;
+#else
+
+ for (i = 0, c_driver = phy_driver_array[0];
+ c_driver != 0; i++, c_driver = phy_driver_array[i]) {
+ /* phy init first */
+ if (strcmp(c_driver, "FH EPHY") == 0) {
+ fh_pmu_ephy_sel(INTERNAL_PHY);
+ fh_gmac_ephy_reset(gmac, INTERNAL_PHY);
+ gmac->phy_sel = INTERNAL_PHY;
+ } else {
+ external_phy_pin_sel(gmac, 1);
+ switch_flag = 1;
+ fh_pmu_ephy_sel(EXTERNAL_PHY);
+ fh_gmac_ephy_reset(gmac, EXTERNAL_PHY);
+ gmac->phy_sel = EXTERNAL_PHY;
+ }
+ /* find phy id.. */
+ ret = scan_vaild_phy_id(gmac, phy_support_list,
+ ARRAY_SIZE(phy_support_list));
+ if (!ret)
+ break;
+ /*restore extenal pin set.*/
+ if (switch_flag)
+ external_phy_pin_sel(gmac, 0);
+
+ }
+
+ if (!c_driver) {
+ pr_err("find no phy..\n");
+ gmac->phy_sel = 0;
+ if (switch_flag)
+ external_phy_pin_sel(gmac, 0);
+ return -1;
+ }
+
+ if (strcmp(c_driver, "Generic PHY") == 0)
+ fh_pinctrl_sdev("RMII", 0);
+
+ return 0;
+#endif
+}
+
+static int __fh_mdio_write(Gmac_Object *pGmac, int phyaddr, int phyreg,
+ u16 phydata)
+{
+#ifdef CONFIG_EMULATION
+ return 0;
+#else
+ int timeout = 1000;
+
+ if (phyaddr < 0)
+ return -ENODEV;
+
+ writel(phydata, pGmac->remap_addr + REG_GMAC_GMII_DATA);
+ writel(0x1 << 1 | phyaddr << 11 | gmac_gmii_clock_100_150 << 2 | phyreg
+ << 6 | 0x1, pGmac->remap_addr + REG_GMAC_GMII_ADDRESS);
+
+ while (readl(pGmac->remap_addr + REG_GMAC_GMII_ADDRESS) & 0x1) {
+ udelay(100);
+ timeout--;
+ if (timeout < 0) {
+ pr_err("ERROR: %s, timeout, phyaddr: %d, phyreg: 0x%x, phydata: 0x%x\n",
+ __func__, phyaddr, phyreg, phydata);
+ break;
+ }
+ }
+ return 0;
+#endif
+}
+
+
+static int fh_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
+{
+ struct net_device *ndev = bus->priv;
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ return __fh_mdio_read(pGmac, phyaddr, phyreg);
+}
+
+static int fh_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
+ u16 phydata)
+{
+ struct net_device *ndev = bus->priv;
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ return __fh_mdio_write(pGmac, phyaddr, phyreg, phydata);
+}
+
+
+static int fh_gmac_ephy_reset(Gmac_Object *pGmac, __u32 phy_sel)
+{
+ int ret = 0;
+#if defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x)
+ if (phy_sel == EXTERNAL_PHY) {
+ ret = gpio_request(pGmac->phyreset_gpio, "phyreset-gpio");
+ if (ret) {
+ pr_err("%s: ERROR: request reset pin : %d failed\n",
+ __func__, pGmac->phyreset_gpio);
+ ret = -ENODEV;
+ return ret;
+ }
+
+ gpio_direction_output(pGmac->phyreset_gpio,
+ GPIOF_OUT_INIT_HIGH);
+ gpio_direction_output(pGmac->phyreset_gpio,
+ GPIOF_OUT_INIT_LOW);
+ /* actual is 20ms */
+ usleep_range(10000, 20000);
+ gpio_direction_output(pGmac->phyreset_gpio,
+ GPIOF_OUT_INIT_HIGH);
+ usleep_range(150000, 200000);
+
+ gpio_free(pGmac->phyreset_gpio);
+
+ return ret;
+ }
+ fh_pmu_internal_ephy_reset();
+#else
+
+ ret = gpio_request(pGmac->phyreset_gpio, "phyreset-gpio");
+ if (ret) {
+ pr_err("%s: ERROR: request reset pin : %d failed\n",
+ __func__, pGmac->phyreset_gpio);
+ ret = -ENODEV;
+ return ret;
+ }
+
+ gpio_direction_output(pGmac->phyreset_gpio, GPIOF_OUT_INIT_HIGH);
+ gpio_direction_output(pGmac->phyreset_gpio, GPIOF_OUT_INIT_LOW);
+ /* actual is 20ms */
+ usleep_range(10000, 20000);
+ gpio_direction_output(pGmac->phyreset_gpio, GPIOF_OUT_INIT_HIGH);
+ usleep_range(150000, 200000);
+
+ gpio_free(pGmac->phyreset_gpio);
+
+ return ret;
+
+#endif
+ return 0;
+}
+
+
+
+int fh_mdio_reset(struct mii_bus *bus)
+{
+ struct net_device *ndev = bus->priv;
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ fh_pmu_ephy_sel(pGmac->phy_sel);
+
+ pGmac->phy_reset = fh_gmac_ephy_reset;
+
+ return pGmac->phy_reset(pGmac, pGmac->phy_sel);
+}
+
+static int fh_mdio_set_mii(struct mii_bus *bus)
+{
+ struct net_device *ndev = bus->priv;
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ __u32 rmii_mode;
+ __u32 ret;
+ int phyid = pGmac->phyid;
+
+ if (pGmac->phydev == NULL)
+ return -ENODEV;
+
+ switch (pGmac->phydev->phy_id) {
+ case FH_GMAC_PHY_RTL8201:
+ fh_mdio_write(bus, phyid,
+ gmac_phyt_rtl8201_page_select, 7);
+ fh_mdio_write(bus, phyid,
+ gmac_phyt_rtl8201_rmii_mode, 0x1ffa);
+ fh_mdio_write(bus, phyid,
+ gmac_phyt_rtl8201_page_select, 0);
+ break;
+ case FH_GMAC_PHY_IP101G:
+ fh_mdio_write(bus, phyid,
+ gmac_phyt_ip101g_page_select, 16);
+ fh_mdio_write(bus, phyid,
+ gmac_phyt_rtl8201_rmii_mode, 0x1006);
+ fh_mdio_write(bus, phyid,
+ gmac_phyt_ip101g_page_select, 0x10);
+ break;
+ case FH_GMAC_PHY_TI83848:
+ rmii_mode = fh_mdio_read(bus, phyid,
+ gmac_phyt_ti83848_rmii_mode);
+ rmii_mode |= 0x20;
+ fh_mdio_write(bus, phyid,
+ gmac_phyt_ti83848_rmii_mode, rmii_mode);
+ break;
+ case FH_GMAC_PHY_INTERNAL:
+ pr_info("found fh internel phy...\n");
+ /* switch to page 1 */
+ fh_mdio_write(bus, phyid, 0x1f, 0x100);
+ /* Disable APS */
+ fh_mdio_write(bus, phyid, 0x12, 0x4824);
+ /*switch to page 2*/
+ fh_mdio_write(bus, phyid, 0x1f, 0x200);
+ /* PHY AFE TRX optimization */
+ fh_mdio_write(bus, phyid, 0x18, 0);
+ /* switch to page 6 */
+ fh_mdio_write(bus, phyid, 0x1f, 0x600);
+ /* PHY AFE ADC optimization */
+ fh_mdio_write(bus, phyid, 0x10, 0x555b);
+ /* PHYAFE TX optimization */
+ fh_mdio_write(bus, phyid, 0x14, 0x708f);
+ /* CP current optimization */
+ fh_mdio_write(bus, phyid, 0x17, 0x575);
+ /* ADC OP BIAS optimization */
+ fh_mdio_write(bus, phyid, 0x18, 0);
+ /* RX signal detector level optimization */
+ fh_mdio_write(bus, phyid, 0x19, 0x408);
+ /* PHY AEF PDCW optimization */
+ fh_mdio_write(bus, phyid, 0x1c, 0x8880);
+
+ /*drive set below.*/
+ /*first debug open*/
+ fh_mdio_write(bus, phyid, 0x1f, 0x800);
+ fh_mdio_write(bus, phyid, 0x1d, 0x844);
+ fh_mdio_write(bus, phyid, 0x1f, 0x600);
+ fh_mdio_write(bus, phyid, 0x15, 0x1320);
+
+ fh_mdio_write(bus, phyid, 0x1f, 0x600);
+ ret = fh_mdio_read(bus, phyid, 21);
+ ret &= ~(0x1f << 8 | 0x1f);
+ ret |= 0x10 << 8 | 0x1f | 1 << 13;
+ fh_mdio_write(bus, phyid, 21, ret);
+
+ //read back debug data
+ fh_mdio_write(bus, phyid, 0x1f, 0x800);
+ ret = fh_mdio_read(bus, phyid, 0x1e);
+ pr_err("AFE driver [Raw] : [100M] : [10M] = [%x] : [%x] : [%x]\n",
+ ret, (ret >> 8) & 0x1f, (ret & 0x1f));
+ break;
+
+ default:
+#ifdef CONFIG_EMULATION
+ return 0;
+#else
+ return -ENODEV;
+#endif
+ }
+
+ return 0;
+}
+
+int fh_mdio_register(struct net_device *ndev)
+{
+ int err = 0, found, addr;
+ struct mii_bus *new_bus;
+ Gmac_Object *pGmac = netdev_priv(ndev);
+ struct mdio_device *mdiodev = NULL;
+
+ new_bus = mdiobus_alloc();
+ if (new_bus == NULL)
+ return -ENOMEM;
+ new_bus->name =
+ pGmac->phy_interface ==
+ PHY_INTERFACE_MODE_MII ? "gmac_mii" : "gmac_rmii";
+ new_bus->read = &fh_mdio_read;
+ new_bus->write = &fh_mdio_write;
+ new_bus->reset = &fh_mdio_reset;
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+ new_bus->priv = ndev;
+ new_bus->parent = pGmac->dev;
+ err = mdiobus_register(new_bus);
+ if (err != 0) {
+ pr_err("%s: Cannot register as MDIO bus, error: %d\n",
+ new_bus->name, err);
+ goto bus_register_fail;
+ }
+
+ pGmac->mii = new_bus;
+
+ found = 0;
+ for (addr = 0; addr < 32; addr++) {
+ mdiodev = new_bus->mdio_map[addr];
+ if (mdiodev) {
+ if (pGmac->phyid == -1)
+ pGmac->phyid = addr;
+
+ found = 1;
+ pGmac->phydev = to_phy_device(&mdiodev->dev);
+ break;
+ }
+ }
+
+ if (pGmac->mii == NULL || mdiodev == NULL) {
+ pr_warn("%s: MII BUS or phydev is NULL\n", ndev->name);
+ err = -ENXIO;
+ goto bus_register_fail;
+ }
+
+ err = fh_mdio_set_mii(pGmac->mii);
+
+ if (!found || err) {
+ pr_warn("%s: No PHY found\n", ndev->name);
+ err = -ENXIO;
+ goto bus_register_fail;
+ }
+
+ pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n",
+ ndev->name, pGmac->phydev->phy_id, addr,
+ pGmac->phydev->irq, dev_name(&pGmac->phydev->mdio.dev),
+ (addr ==
+ pGmac->phyid) ? " active" : "");
+
+ return 0;
+
+bus_register_fail:
+ pGmac->phydev = NULL;
+ mdiobus_unregister(new_bus);
+ mdiobus_free(new_bus);
+ return err;
+}
+
+int fh_mdio_unregister(struct net_device *ndev)
+{
+ Gmac_Object *pGmac = netdev_priv(ndev);
+
+ mdiobus_unregister(pGmac->mii);
+ mdiobus_free(pGmac->mii);
+ pGmac->mii->priv = NULL;
+ pGmac->phydev = NULL;
+ return 0;
+}
diff --git a/drivers/net/ethernet/fullhan/fh_gmac_phyt.h b/drivers/net/ethernet/fullhan/fh_gmac_phyt.h
new file mode 100644
index 00000000..509782fb
--- /dev/null
+++ b/drivers/net/ethernet/fullhan/fh_gmac_phyt.h
@@ -0,0 +1,97 @@
+/*
+ * fh_gmac_phyt.h
+ *
+ * Created on: May 22, 2014
+ * Author: duobao
+ */
+
+#ifndef FH_GMAC_PHYT_H_
+#define FH_GMAC_PHYT_H_
+#include "fh_gmac.h"
+
+#define FH_GMAC_PHY_IP101G 0x02430C54
+#define FH_GMAC_PHY_RTL8201 0x001CC816
+#define FH_GMAC_PHY_TI83848 0xFFFFFFFF
+#define FH_GMAC_PHY_INTERNAL 0x441400
+
+enum
+{
+ gmac_phyt_speed_10M_half_duplex = 1,
+ gmac_phyt_speed_100M_half_duplex = 2,
+ gmac_phyt_speed_10M_full_duplex = 5,
+ gmac_phyt_speed_100M_full_duplex = 6
+};
+
+
+typedef union
+{
+ struct
+ {
+ __u32 reserved_6_0 :7;
+ __u32 collision_test :1;
+ __u32 duplex_mode :1;
+ __u32 restart_auto_negotiate :1;
+ __u32 isolate :1;
+ __u32 power_down :1;
+ __u32 auto_negotiate_enable :1;
+ __u32 speed_select :1;
+ __u32 loopback :1;
+ __u32 reset :1;
+ __u32 reserved_31_16 :16;
+ }bit;
+ __u32 dw;
+}Reg_Phyt_Basic_Ctrl;
+
+
+typedef union
+{
+ struct
+ {
+ __u32 extended_capabilities :1;
+ __u32 jabber_detect :1;
+ __u32 link_status :1;
+ __u32 auto_negotiate_ability :1;
+ __u32 remote_fault :1;
+ __u32 auto_negotiate_complete :1;
+ __u32 reserved_10_6 :5;
+ __u32 base_t_half_duplex_10 :1;
+ __u32 base_t_full_duplex_10 :1;
+ __u32 base_tx_half_duplex_100 :1;
+ __u32 base_tx_full_duplex_100 :1;
+ __u32 base_t_4 :1;
+ __u32 reserved_31_16 :16;
+ }bit;
+ __u32 dw;
+}Reg_Phyt_Basic_Status;
+
+typedef union
+{
+ struct
+ {
+ __u32 scramble_disable :1;
+ __u32 reserved_1 :1;
+ __u32 speed_indication :3;
+ __u32 reserved_5 :1;
+ __u32 enable_4b5b :1;
+ __u32 gpo :3;
+ __u32 reserved_11_10 :2;
+ __u32 auto_done :1;
+ __u32 reserved_31_13 :19;
+ }bit;
+ __u32 dw;
+}Reg_Phyt_Special_Status;
+
+enum {
+ gmac_phyt_reg_basic_ctrl = 0,
+ gmac_phyt_reg_basic_status = 1,
+ gmac_phyt_reg_phy_id1 = 2,
+ gmac_phyt_reg_phy_id2 = 3,
+ gmac_phyt_rtl8201_rmii_mode = 16,
+ gmac_phyt_ti83848_rmii_mode = 17,
+ gmac_phyt_rtl8201_power_saving = 24,
+ gmac_phyt_rtl8201_page_select = 31,
+ gmac_phyt_ip101g_page_select = 20
+};
+
+int fh_phy_reset_api(struct phy_device *phydev);
+#endif /* FH_GMAC_PHYT_H_ */
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 5fde8e33..77538fcf 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -966,6 +966,7 @@ void phy_state_machine(struct work_struct *work)
enum phy_state old_state;
int err = 0;
int old_link;
+ int time_interval = PHY_STATE_TIME * HZ;
mutex_lock(&phydev->lock);
@@ -982,7 +983,7 @@ void phy_state_machine(struct work_struct *work)
break;
case PHY_UP:
needs_aneg = true;
-
+ time_interval = 0;
phydev->link_timeout = PHY_AN_TIMEOUT;
break;
@@ -1022,7 +1023,7 @@ void phy_state_machine(struct work_struct *work)
break;
if (phydev->link) {
- if (AUTONEG_ENABLE == phydev->autoneg) {
+ if (phydev->autoneg == AUTONEG_ENABLE) {
err = phy_aneg_done(phydev);
if (err < 0)
break;
@@ -1036,6 +1037,15 @@ void phy_state_machine(struct work_struct *work)
phydev->state = PHY_RUNNING;
netif_carrier_on(phydev->attached_dev);
phydev->adjust_link(phydev->attached_dev);
+ } else {
+ phydev->link_down_times++;
+ if (phydev->link_down_times > 5) {
+ if (phydev->drv->no_link_timeout_process) {
+ pr_err("linkdown . reset phy...\n");
+ phydev->drv->no_link_timeout_process(phydev);
+ }
+ phydev->link_down_times = 0;
+ }
}
break;
case PHY_FORCING:
@@ -1164,7 +1174,7 @@ void phy_state_machine(struct work_struct *work)
*/
if (phydev->irq == PHY_POLL)
queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
- PHY_STATE_TIME * HZ);
+ time_interval);
}
void phy_mac_interrupt(struct phy_device *phydev, int new_link)
diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h
index d1092421..945bcefa 100644
--- a/drivers/net/usb/asix.h
+++ b/drivers/net/usb/asix.h
@@ -153,8 +153,7 @@
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
-#define AX_DEFAULT_RX_CTL (AX_RX_CTL_SO | AX_RX_CTL_AB)
-
+#define AX_DEFAULT_RX_CTL (AX_RX_CTL_AB)
/* GPIO 0 .. 2 toggles */
#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index 125cff57..4a6b7fc2 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -387,7 +387,7 @@ void asix_set_multicast(struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
struct asix_data *data = (struct asix_data *)&dev->data;
- u16 rx_ctl = AX_DEFAULT_RX_CTL;
+ u16 rx_ctl = AX_DEFAULT_RX_CTL | AX_RX_CTL_SO;
if (net->flags & IFF_PROMISC) {
rx_ctl |= AX_RX_CTL_PRO;
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
index 5be6b674..f465708c 100644
--- a/drivers/net/usb/asix_devices.c
+++ b/drivers/net/usb/asix_devices.c
@@ -325,7 +325,7 @@ static int ax88772_link_reset(struct usbnet *dev)
ethtool_cmd_speed(&ecmd), ecmd.duplex, mode);
asix_write_medium_mode(dev, mode, 0);
-
+ asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL | AX_RX_CTL_SO, 0);
return 0;
}
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 4ab82b99..1c9abd58 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -48,7 +48,6 @@
#define DRIVER_VERSION "22-Aug-2005"
-
/*-------------------------------------------------------------------------*/
/*
@@ -203,7 +202,23 @@ static void intr_complete (struct urb *urb)
break;
}
- status = usb_submit_urb (urb, GFP_ATOMIC);
+ queue_delayed_work(system_power_efficient_wq,
+ &dev->status_work, msecs_to_jiffies(30));
+ return;
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status != 0)
+ netif_err(dev, timer, dev->net,
+ "intr resubmit --> %d\n", status);
+}
+
+static void usbnet_status_func(struct work_struct *work)
+{
+ int status;
+ struct usbnet *dev = container_of(work, struct usbnet,
+ status_work.work);
+
+ status = usb_submit_urb(dev->interrupt, GFP_ATOMIC);
if (status != 0)
netif_err(dev, timer, dev->net,
"intr resubmit --> %d\n", status);
@@ -1663,6 +1678,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
mutex_init (&dev->phy_mutex);
mutex_init(&dev->interrupt_mutex);
dev->interrupt_count = 0;
+ INIT_DELAYED_WORK(&dev->status_work, usbnet_status_func);
dev->net = net;
strcpy (net->name, "usb%d");
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 3fd1cc98..8cc671a2 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -1178,7 +1178,10 @@ static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap,
return -EINVAL;
ev = (struct wmi_pstream_timeout_event *) datap;
-
+ if (ev->traffic_class >= WMM_NUM_AC) {
+ ath6kl_err("invalid traffic class: %d\n", ev->traffic_class);
+ return -EINVAL;
+ }
/*
* When the pstream (fat pipe == AC) timesout, it means there were
* no thinStreams within this pstream & it got implicitly created
@@ -1519,6 +1522,10 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
return -EINVAL;
reply = (struct wmi_cac_event *) datap;
+ if (reply->ac >= WMM_NUM_AC) {
+ ath6kl_err("invalid AC: %d\n", reply->ac);
+ return -EINVAL;
+ }
if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
(reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) {
@@ -2635,7 +2642,7 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class,
u16 active_tsids = 0;
int ret;
- if (traffic_class > 3) {
+ if (traffic_class >= WMM_NUM_AC) {
ath6kl_err("invalid traffic class: %d\n", traffic_class);
return -EINVAL;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index 78d59a67..32b6b9ef 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -1236,6 +1236,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
}
switch (element_id) {
case WLAN_EID_SSID:
+ if (element_len > IEEE80211_MAX_SSID_LEN)
+ return -EINVAL;
bss_entry->ssid.ssid_len = element_len;
memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
element_len);
@@ -1245,6 +1247,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break;
case WLAN_EID_SUPP_RATES:
+ if (element_len > MWIFIEX_SUPPORTED_RATES)
+ return -EINVAL;
memcpy(bss_entry->data_rates, current_ptr + 2,
element_len);
memcpy(bss_entry->supported_rates, current_ptr + 2,
@@ -1254,6 +1258,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break;
case WLAN_EID_FH_PARAMS:
+ if (element_len + 2 < sizeof(*fh_param_set))
+ return -EINVAL;
fh_param_set =
(struct ieee_types_fh_param_set *) current_ptr;
memcpy(&bss_entry->phy_param_set.fh_param_set,
@@ -1262,6 +1268,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break;
case WLAN_EID_DS_PARAMS:
+ if (element_len + 2 < sizeof(*ds_param_set))
+ return -EINVAL;
ds_param_set =
(struct ieee_types_ds_param_set *) current_ptr;
@@ -1273,6 +1281,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break;
case WLAN_EID_CF_PARAMS:
+ if (element_len + 2 < sizeof(*cf_param_set))
+ return -EINVAL;
cf_param_set =
(struct ieee_types_cf_param_set *) current_ptr;
memcpy(&bss_entry->ss_param_set.cf_param_set,
@@ -1281,6 +1291,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break;
case WLAN_EID_IBSS_PARAMS:
+ if (element_len + 2 < sizeof(*ibss_param_set))
+ return -EINVAL;
ibss_param_set =
(struct ieee_types_ibss_param_set *)
current_ptr;
@@ -1290,10 +1302,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break;
case WLAN_EID_ERP_INFO:
+ if (!element_len)
+ return -EINVAL;
bss_entry->erp_flags = *(current_ptr + 2);
break;
case WLAN_EID_PWR_CONSTRAINT:
+ if (!element_len)
+ return -EINVAL;
bss_entry->local_constraint = *(current_ptr + 2);
bss_entry->sensed_11h = true;
break;
@@ -1333,6 +1349,9 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
break;
case WLAN_EID_VENDOR_SPECIFIC:
+ if (element_len + 2 < sizeof(vendor_ie->vend_hdr))
+ return -EINVAL;
+
vendor_ie = (struct ieee_types_vendor_specific *)
current_ptr;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 7dc726d7..9f989345 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -220,6 +220,13 @@ config BCM_KONA_USB2_PHY
help
Enable this to support the Broadcom Kona USB 2.0 PHY.
+config FH_USB2_PHY
+ tristate "Fullhan USB2 PHY Driver"
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to support the Fullhan USB 2.0 PHY.
+
config PHY_EXYNOS5250_SATA
tristate "Exynos5250 Sata SerDes/PHY driver"
depends on SOC_EXYNOS5250
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index a534cf5b..2097c781 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o
obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
+obj-$(CONFIG_FH_USB2_PHY) += phy-fullhan-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
diff --git a/drivers/phy/phy-fullhan-usb2.c b/drivers/phy/phy-fullhan-usb2.c
new file mode 100644
index 00000000..0d0eda09
--- /dev/null
+++ b/drivers/phy/phy-fullhan-usb2.c
@@ -0,0 +1,116 @@
+/*
+ * phy-fullhan-usb2.c - Fullhan USB2 Phy Driver
+ *
+ * Copyright (C) 2013 Linaro Limited
+ * Fullhan <fh@fullhan.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+struct fullhan_usb {
+ void __iomem *regs;
+};
+
+static void fullhan_usb_phy_power(struct fullhan_usb *phy, int on)
+{
+
+}
+
+static int fullhan_usb_phy_init(struct phy *gphy)
+{
+ /*struct fullhan_usb *phy = phy_get_drvdata(gphy);*/
+
+ return 0;
+}
+
+static int fullhan_usb_phy_power_on(struct phy *gphy)
+{
+ struct fullhan_usb *phy = phy_get_drvdata(gphy);
+
+ fullhan_usb_phy_power(phy, 1);
+
+ return 0;
+}
+
+static int fullhan_usb_phy_power_off(struct phy *gphy)
+{
+ struct fullhan_usb *phy = phy_get_drvdata(gphy);
+
+ fullhan_usb_phy_power(phy, 0);
+
+ return 0;
+}
+
+static struct phy_ops ops = {
+ .init = fullhan_usb_phy_init,
+ .power_on = fullhan_usb_phy_power_on,
+ .power_off = fullhan_usb_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int fullhan_usb2_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct fullhan_usb *phy;
+ /*struct resource *res;*/
+ struct phy *gphy;
+ struct phy_provider *phy_provider;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, phy);
+
+ gphy = devm_phy_create(dev, NULL, &ops);
+ if (IS_ERR(gphy))
+ return PTR_ERR(gphy);
+
+ /* The PHY supports an 8-bit wide UTMI interface */
+ phy_set_bus_width(gphy, 8);
+
+ phy_set_drvdata(gphy, phy);
+
+ phy_provider = devm_of_phy_provider_register(dev,
+ of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id fullhan_usb2_dt_ids[] = {
+ { .compatible = "fh,fh-usb2-phy" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, fullhan_usb2_dt_ids);
+
+static struct platform_driver fullhan_usb2_driver = {
+ .probe = fullhan_usb2_probe,
+ .driver = {
+ .name = "fullhan-usb2",
+ .of_match_table = fullhan_usb2_dt_ids,
+ },
+};
+
+module_platform_driver(fullhan_usb2_driver);
+
+MODULE_ALIAS("platform:fullhan-usb2");
+MODULE_AUTHOR("Fullhan <fh@fullhan.com>");
+MODULE_DESCRIPTION("Fullhan USB 2.0 PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index b0c0fa04..0ac27174 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -24,6 +24,16 @@ config DEBUG_PINCTRL
help
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
+config PINCTRL_FULLHAN
+ bool "Fulhan pin controller driver"
+ depends on ARCH_FULLHAN && USE_OF
+ select PINMUX
+ default y
+ help
+ This is the pin controller driver for FullHan processors.
+ This option is selected automatically when specific
+ machine and arch are selected to build.
+
config PINCTRL_ADI2
bool "ADI pin controller driver"
depends on (BF54x || BF60x)
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 11bad373..9c3c96c1 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -37,6 +37,8 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
+obj-$(CONFIG_PINCTRL_FULLHAN) += pinctrl-fullhan.o
+
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-y += bcm/
obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
diff --git a/drivers/pinctrl/pinctrl-fullhan-utils.h b/drivers/pinctrl/pinctrl-fullhan-utils.h
new file mode 100644
index 00000000..1f63d7ca
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-fullhan-utils.h
@@ -0,0 +1,254 @@
+/*
+ * Core driver for Fullhan pin controller
+ *
+ * Copyright (C) 2018 Shanghai Fullhan Microelectronics Co., Ltd.
+ *
+ * Author: Wang Yuliang <wangyl307@fullhan.com>
+ *
+ */
+
+#ifndef __PINCTRL_FULLHAN_UTILS_H
+#define __PINCTRL_FULLHAN_UTILS_H
+
+#include "pinctrl-fullhan.h"
+
+static struct fh_pingroup *fh_pinctrl_find_group_by_name(
+ const struct fh_pinctrl_soc_info *info, const char *name)
+{
+ struct fh_pingroup *grp = NULL;
+ int i;
+
+ for (i = 0; i < info->ngroups; i++) {
+ if (!strncmp(info->pin_groups[i].name, name, MAX_NAME_CHARS)) {
+ grp = &info->pin_groups[i];
+ break;
+ }
+ }
+ return grp;
+}
+
+static struct fh_pinmux *fh_pinctrl_find_mux_by_name(const char *name,
+ const struct fh_pinctrl_soc_info *info) {
+ int i;
+ struct fh_pinmux *mux = info->pin_muxs;
+
+ for (i = 0; i < info->nmuxs; i++, mux++) {
+ if (!strncmp(name, mux->name, MAX_NAME_CHARS))
+ return mux;
+ }
+
+ return NULL;
+}
+
+static int fh_pinctrl_get_pin_id(const struct fh_pingroup *group,
+ unsigned int pin_index)
+{
+ struct fh_pin *pin;
+ struct fh_pinmux *mux;
+
+ if (pin_index >= group->npins)
+ return -1001;
+ pin = &group->pins[pin_index];
+ if (!pin)
+ return -1002;
+ mux = pin->mux;
+ if (!mux)
+ return -1003;
+ if (pin->mux_sel >= mux->npads) {
+ DBG_LINE_ARGS("%s %s %d %d\n",
+ pin->name, mux->name, pin->mux_sel, mux->npads);
+ return -1004;
+ }
+
+ return mux->pads[pin->mux_sel]->index;
+}
+
+static int fh_pinctrl_find_func_in_pad(const char *func,
+ const struct fh_pinpad *pad)
+{
+ int i = 0;
+
+ if (!func || !pad || !pad->funcs)
+ return -EINVAL;
+ for (i = 0; i < pad->nfunc; i++) {
+ if (strncmp(func, pad->funcs[i], MAX_NAME_CHARS) == 0)
+ return i; /* return the index of func in pad*/
+ }
+ return -3001;
+}
+
+static int fh_pinctrl_check_pin_config(const fh_pin_reg *config)
+{
+ if (!config || !config->dw)
+ return -2101;
+ if (config->dw & (~0x1F111171)) /* error when other bits was set */
+ {
+ DBG_LINE_ARGS("%x %x", config->dw, config->dw & (~0x1F111171));
+ return -2102;
+ }
+ if (config->bit.pu && config->bit.pd)
+ return -2103;
+ return 0;
+}
+
+static struct fh_pinctrl_soc_info fh_pinctrl_info;
+
+static int fh_pinctrl_set_pin_pupd(fh_pin_reg *config, int pupd)
+{
+ if (!config || pupd < 0 || pupd > 2)
+ return -2001;
+ switch (pupd) {
+ case PUPD_NONE:
+ config->bit.pu = fh_pinctrl_info.pupd_zero;
+ config->bit.pd = fh_pinctrl_info.pupd_zero;
+ break;
+ case PUPD_UP:
+ config->bit.pu = fh_pinctrl_info.pupd_enable;
+ config->bit.pd = fh_pinctrl_info.pupd_disable;
+ break;
+ case PUPD_DOWN:
+ config->bit.pu = fh_pinctrl_info.pupd_disable;
+ config->bit.pd = fh_pinctrl_info.pupd_enable;
+ break;
+ default:
+ return -2002;
+ break;
+ }
+
+ return 0;
+}
+
+static int fh_pinctrl_set_pin_config(fh_pin_reg *config, int pupd, int ds)
+{
+ int ret;
+
+ if (!config || pupd < 0 || ds < 0)
+ return -2001;
+ config->bit.ds = ds;
+
+ ret = fh_pinctrl_set_pin_pupd(config, pupd);
+ if (ret)
+ return ret;
+
+ /* fix on configs */
+ config->bit.st = 1;
+ config->bit.ie = 1;
+
+ return fh_pinctrl_check_pin_config(config);
+}
+
+static void fh_pinctrl_update_pad_reg(struct fh_pinpad *pad)
+{
+ int ret = fh_pinctrl_check_pin_config(&pad->config);
+
+ if (ret)
+ pr_err("PIN %d config [0x%08x] err: %d\n",
+ pad->index, pad->config.dw, ret);
+
+ pad->func_sel = pad->config.bit.mfs;
+ SET_REG(pad->reg, pad->config.dw);
+}
+
+static int fh_pinctrl_set_gpio_func(struct fh_pinpad *pad) {
+ int i;
+
+ if (!pad || !pad->funcs || pad->index < 0)
+ return -EINVAL;
+ for (i = 0; i < pad->nfunc; i++) {
+ if (strncmp("GPIO", pad->funcs[i], 4) == 0) {
+ pad->config.bit.mfs = i;
+ fh_pinctrl_update_pad_reg(pad);
+ pr_info("[PINCTRL] pad %d set to func %s\n",
+ pad->index, pad->funcs[i]);
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int fh_pinctrl_check_duplicate_pin(unsigned int pin_id,
+ const struct fh_pinctrl_soc_info *info)
+{
+ struct fh_pinpad *pad;
+ const struct fh_pinpad *p;
+ int i;
+
+ if (!info || pin_id >= info->npins)
+ return -1;
+
+ pad = &info->pin_pads[pin_id];
+
+ for (i = 0; i < info->npins; i++) {
+ p = &info->pin_pads[i];
+ if (p->funcs && pad->funcs && p != pad) {
+ const char* n1 = p->funcs[p->config.bit.mfs];
+ const char* n2 = pad->funcs[pad->config.bit.mfs];
+ if (!strncmp(n1, n2, MAX_NAME_CHARS)) {
+ pr_err("[PINCTRL] WARNING: %s already exists in pad %d\n",
+ n1, p->index);
+ fh_pinctrl_set_gpio_func(&info->pin_pads[i]);
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+static int fh_pinctrl_check_padlist(const struct fh_pinctrl_soc_info *info)
+{
+ int i;
+ struct fh_pinpad *pad;
+
+ for (i = 0; i < info->npins; i++) {
+ pad = &info->pin_pads[i];
+ if (pad->index < 0 || pad->func_sel < 0) {
+ pr_err("[PINCTRL] ERROR: pad %2d[0x%03x] is still empty\n",
+ i, (int)pad->reg & 0xfff);
+ }
+ }
+
+ return 0;
+}
+
+static void fh_pinctrl_print_pin_info(const struct fh_pinpad *pad,
+ struct seq_file *s, int show_all)
+{
+ char *pupd;
+ fh_pin_reg config;
+ struct fh_pinctrl_soc_info *info = &fh_pinctrl_info;
+
+ if (!pad || pad->index < 0) {
+ if (!show_all)
+ return;
+ seq_printf(s, "N/A");
+ return;
+ }
+
+ config = pad->config;
+
+ if (config.bit.pu == info->pupd_enable &&
+ config.bit.pd == info->pupd_disable)
+ pupd = "PU";
+ else if (config.bit.pu == info->pupd_disable &&
+ config.bit.pd == info->pupd_enable)
+ pupd = "PD";
+ else if (config.bit.pu == info->pupd_zero &&
+ config.bit.pd == info->pupd_zero)
+ pupd = "NONE";
+ else
+ pupd = "ERR";
+
+ seq_printf(s, "%02d\t%8s\t0x%04x\t0x%08x%4d%4d%4d%8s%4d",
+ pad->index,
+ pad->funcs ? pad->funcs[config.bit.mfs]:"N/A",
+ (int)pad->reg & 0xfff,
+ GET_REG(pad->reg),
+ config.bit.mfs,
+ config.bit.ie,
+ config.bit.oe,
+ pupd,
+ config.bit.ds);
+}
+
+
+#endif /* __PINCTRL_FULLHAN_UTILS_H */
diff --git a/drivers/pinctrl/pinctrl-fullhan.c b/drivers/pinctrl/pinctrl-fullhan.c
new file mode 100644
index 00000000..898ea773
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-fullhan.c
@@ -0,0 +1,1089 @@
+/*
+ * Core driver for Fullhan pin controller
+ *
+ * Copyright (C) 2018 Shanghai Fullhan Microelectronics Co., Ltd.
+ *
+ * Author: Wang Yuliang <wangyl307@fullhan.com>
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <mach/pmu.h>
+
+#include "core.h"
+#include "pinctrl-fullhan.h"
+#include "pinctrl-fullhan-utils.h"
+
+
+
+static int fh_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ return info->ngroups;
+}
+
+static const char *fh_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ return info->pin_groups[selector].name;
+}
+
+static int fh_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ const unsigned **pins,
+ unsigned *npins)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+
+ if (selector >= info->ngroups)
+ return -EINVAL;
+
+ *pins = info->pin_groups[selector].pin_ids;
+ *npins = info->pin_groups[selector].npins;
+
+ return 0;
+}
+
+static void fh_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+
+ if (info)
+ fh_pinctrl_print_pin_info(&info->pin_pads[offset], s, 1);
+}
+
+static int fh_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ const struct fh_pingroup *grp;
+ struct pinctrl_map *new_map;
+ struct device_node *parent;
+ int map_num = 1;
+
+ /*
+ * first find the group of this node and check if we need create
+ * config maps for pins
+ */
+ grp = fh_pinctrl_find_group_by_name(info, np->name);
+ if (!grp) {
+ dev_err(info->dev, "unable to find group for node %s\n",
+ np->name);
+ return -EINVAL;
+ }
+
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, new_map, map_num);
+
+ *map = new_map;
+ *num_maps = map_num;
+
+
+ parent = of_get_parent(np);
+ if (!parent) {
+ kfree(new_map);
+ return -EINVAL;
+ }
+ new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+ new_map[0].data.mux.function = parent->name;
+ new_map[0].data.mux.group = grp->name;
+ of_node_put(parent);
+
+ dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+ new_map->data.mux.function, new_map->data.mux.group, map_num);
+
+ return 0;
+}
+
+static void fh_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+
+ PINCTRL_DEVM_KFREE(info->dev, map);
+}
+
+static const struct pinctrl_ops fh_pinctrl_ops = {
+ .get_groups_count = fh_get_groups_count,
+ .get_group_name = fh_get_group_name,
+ .get_group_pins = fh_get_group_pins,
+ .pin_dbg_show = fh_pin_dbg_show,
+ .dt_node_to_map = fh_dt_node_to_map,
+ .dt_free_map = fh_dt_free_map,
+};
+
+
+static int fh_pmx_set_group(const struct fh_pingroup *grp,
+ const struct fh_pinctrl_soc_info *info)
+{
+ struct fh_pinpad *pad;
+ int i;
+
+ if (!grp || grp->npins == 0)
+ return -EINVAL;
+
+ for (i = 0; i < grp->npins; i++) {
+ const struct fh_pin *pin = &grp->pins[i];
+
+ if (pin->mux_sel >= pin->mux->npads) {
+ pr_err("[PINCTRL] set mux %s error, muxsel out of range\n",
+ pin->name);
+ continue;
+ }
+ pad = pin->mux->pads[pin->mux_sel];
+ pad->config = pin->config;
+ if (pin->mux->ds >= 0)
+ pad->config.bit.ds = pin->mux->ds;
+ pin->mux->select = pin->mux_sel;
+
+ fh_pinctrl_check_duplicate_pin(pad->index, info);
+ fh_pinctrl_update_pad_reg(pad);
+
+ dev_dbg(info->dev, "write pin reg: id %2d, offset 0x%03x, "
+ "val 0x%08x, %s\n",
+ pad->index, (int)pad->reg&0xfff, pad->config.dw, pin->name);
+ }
+
+#if defined(CONFIG_ARCH_FH885xV200) || \
+ defined(CONFIG_ARCH_FH865x)
+ if (strncmp(grp->name, "SD1", 3) == 0) {
+ /* set SD1_FUNC_SEL after all mux switch */
+ fh_pmu_set_sdc1_funcsel(grp->pins[0].mux_sel);
+ }
+#endif
+
+ return 0;
+}
+
+static int fh_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ struct fh_pingroup *grp;
+
+ grp = &info->pin_groups[group];
+
+ return fh_pmx_set_group(grp, info);
+}
+
+static int fh_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ return info->nfunctions;
+}
+
+static const char *fh_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ return info->functions[selector].name;
+}
+
+static int fh_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ *groups = info->functions[selector].groups;
+ *num_groups = info->functions[selector].num_groups;
+
+ return 0;
+}
+
+
+static const struct pinmux_ops fh_pmx_ops = {
+ .get_functions_count = fh_pmx_get_funcs_count,
+ .get_function_name = fh_pmx_get_func_name,
+ .get_function_groups = fh_pmx_get_groups,
+ .set_mux = fh_pmx_set,
+};
+
+#ifdef CONFIG_PINCONF
+
+static int fh_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long *config)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ const fh_pin_reg pin_config = info->pin_pads[pin_id].config;
+
+ *config = pin_config.dw & PINCONFIG_MASK;
+
+ return 0;
+}
+
+static int fh_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned pin_id, unsigned long *configs,
+ unsigned num_configs)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ struct fh_pinpad * const pad = &info->pin_pads[pin_id];
+ int i;
+
+ dev_dbg(fhpctl->dev, "pinconf set pin %s\n",
+ info->pins[pin_id].name);
+
+ for (i = 0; i < num_configs; i++) {
+ unsigned int val;
+ val = GET_REG(pad->reg);
+ val &= ~PINCONFIG_MASK;
+ val |= configs[i] & PINCONFIG_MASK;
+ pad->config.dw = val;
+ fh_pinctrl_update_pad_reg(pad);
+ dev_dbg(fhpctl->dev, "write: offset 0x%x val 0x%lx\n",
+ (int)pad->reg&0xfff, configs[i]);
+ }
+
+ return 0;
+}
+
+static void fh_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin_id)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+
+ if (info)
+ fh_pinctrl_print_pin_info(&info->pin_pads[pin_id], s, 1);
+}
+
+static void fh_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned group)
+{
+ struct fh_pinctrl *fhpctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct fh_pinctrl_soc_info *info = fhpctl->info;
+ struct fh_pingroup *grp;
+ int i;
+
+ if (group >= info->ngroups)
+ return;
+
+ seq_printf(s, "\n");
+ grp = &info->pin_groups[group];
+ for (i = 0; i < grp->npins; i++) {
+ int pin_id = fh_pinctrl_get_pin_id(grp, i);
+ fh_pinctrl_print_pin_info(&info->pin_pads[pin_id], s, 1);
+ seq_printf(s, "\n");
+ }
+}
+
+static const struct pinconf_ops fh_pinconf_ops = {
+ .pin_config_get = fh_pinconf_get,
+ .pin_config_set = fh_pinconf_set,
+ .pin_config_dbg_show = fh_pinconf_dbg_show,
+ .pin_config_group_dbg_show = fh_pinconf_group_dbg_show,
+};
+#endif
+
+/*
+ * Check if the DT contains pins in the direct child nodes. This indicates the
+ * newer DT format to store pins. This function returns true if the first found
+ * fh,pins property is in a child of np. Otherwise false is returned.
+ */
+static bool fh_pinctrl_dt_is_flat_functions(struct device_node *np)
+{
+ struct device_node *function_np;
+ struct device_node *pinctrl_np;
+
+ for_each_child_of_node(np, function_np) {
+ if (of_property_read_bool(function_np, "fh,pins"))
+ return true;
+
+ for_each_child_of_node(function_np, pinctrl_np) {
+ if (of_property_read_bool(pinctrl_np, "fh,pins"))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int fh_pinctrl_parse_pinpads(struct device_node *np,
+ struct fh_pinctrl_soc_info *info)
+{
+ struct device_node *child;
+ struct fh_pinpad *pad;
+ const char **funcs;
+ unsigned int npads, index;
+ int nfunc, pupd, ds;
+ int ret = 0;
+
+ npads = of_get_child_count(np);
+
+ dev_info(info->dev, "npads: %d", npads);
+
+ for_each_child_of_node(np, child)
+ {
+ PINCTRL_PARSE_PROPERTY_U32(child, "index", index);
+ if(index >= info->npins) {
+ dev_err(info->dev, "index %d of pad %s out of range",
+ index, child->full_name);
+ return -EINVAL;
+ }
+ pad = &info->pin_pads[index];
+ pad->index = index;
+ pad->name = child->name;
+ pad->reg = info->pin_regs[index];
+
+ PINCTRL_PARSE_PROPERTY_U32(child, "pupd", pupd);
+ PINCTRL_PARSE_PROPERTY_U32(child, "ds", ds);
+
+ pad->config.dw = GET_REG(pad->reg);
+ ret = fh_pinctrl_set_pin_config(&pad->config, pupd, ds);
+ if (ret) {
+ dev_err(info->dev, "error config pupd:%d ds:%d, ret: %d\n",
+ pupd, ds, ret);
+ return ret;
+ }
+
+ /* get nfunc first */
+ nfunc = of_property_count_strings(child, "funcs");
+ if (nfunc <= 0 || nfunc > info->max_mux) {
+ dev_err(info->dev, "wrong nfunc: %d in %s\n",
+ nfunc, child->full_name);
+ return -EINVAL;
+ }
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, funcs, nfunc);
+
+ of_property_read_string_array(child, "funcs", funcs, nfunc);
+ pad->nfunc = nfunc;
+ pad->funcs = funcs;
+ dev_dbg(info->dev, "get %2d func in pad %2d [func0: %s]",
+ pad->nfunc, pad->index, pad->funcs[0]);
+ }
+
+ return 0;
+}
+
+static int fh_pinctrl_parse_pinmuxs(struct device_node *np,
+ struct fh_pinctrl_soc_info *info)
+{
+ struct device_node *child, *np_pad;
+ struct fh_pinmux *mux;
+ unsigned int nmuxs, npads, pad_index;
+ unsigned mux_id = 0;
+ int i = 0, j = 0;
+
+ nmuxs = of_get_child_count(np);
+ dev_dbg(info->dev, "nmuxs: %d", nmuxs);
+
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, info->pin_muxs, nmuxs);
+ info->nmuxs = nmuxs;
+
+ for_each_child_of_node(np, child)
+ {
+ mux = &info->pin_muxs[i++];
+ mux->name = child->name;
+ mux->mux_id = mux_id++;
+ mux->ds = -1;
+ PINCTRL_PARSE_PROPERTY_U32(child, "select", mux->select);
+ of_property_read_u32(child, "ds", &mux->ds);
+ npads = of_count_phandle_with_args(child, "fh,pads", NULL);
+ if (IS_ERR_VALUE(npads))
+ return npads;
+ mux->npads = npads;
+
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, mux->pads, npads);
+
+ dev_dbg(info->dev, "get %d pad in mux %s, sel: %d\n",
+ mux->npads, mux->name, mux->select);
+
+ for (j = 0; j < npads; j++) {
+ np_pad = of_parse_phandle(child, "fh,pads", j);
+ if (!np_pad)
+ return -EINVAL;
+ PINCTRL_PARSE_PROPERTY_U32(np_pad, "index", pad_index);
+ mux->pads[j] = &info->pin_pads[pad_index];
+ if (fh_pinctrl_find_func_in_pad(mux->name, mux->pads[j]) < 0) {
+ return -ENOENT;
+ }
+ dev_dbg(info->dev, "\tpad %d, \n", mux->pads[j]->index);
+ }
+ }
+ return 0;
+}
+
+static int fh_pinctrl_parse_pingroups(struct device_node *np,
+ struct fh_pinctrl_soc_info *info)
+{
+ static const char *cell_name = "#list-cells";
+ struct device_node *child;
+ struct fh_pingroup *group;
+ struct fh_pmx_func *func;
+ struct fh_pin *pin;
+ struct fh_pinpad *pad;
+ struct fh_pinmux *mux;
+ struct of_phandle_args args;
+ unsigned int npins;
+ int pin_id, func_idx;
+ int i = 0, j = 0;
+
+ info->ngroups = of_get_child_count(np);
+ dev_dbg(info->dev, "ngroups: %d", info->ngroups);
+
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, info->pin_groups, info->ngroups);
+
+ func = &info->functions[0];
+ func->name = np->name;
+ func->num_groups = info->ngroups;
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, func->groups, func->num_groups);
+
+ for_each_child_of_node(np, child)
+ {
+ func->groups[i] = child->name;
+ group = &info->pin_groups[i++];
+ group->name = child->name;
+
+ npins = of_count_phandle_with_args(child, "fh,pins", cell_name);
+
+ if (IS_ERR_VALUE(npins))
+ return npins;
+ group->npins = npins;
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, group->pins, npins);
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, group->pin_ids, npins);
+
+ dev_dbg(info->dev, "get %d pins in group %s", group->npins, child->name);
+
+ for (j = 0; j < npins; j++) {
+ if (of_parse_phandle_with_args(child, "fh,pins", cell_name, j, &args)) {
+ return -EINVAL;
+ }
+ pin = &group->pins[j];
+ pin->name = args.np->name;
+
+ mux = fh_pinctrl_find_mux_by_name(pin->name, info);
+
+ if (mux == NULL)
+ return -ENXIO;
+ pin->mux = mux;
+
+ if (args.args_count < 1)
+ pin->mux_sel = pin->mux->select;
+ else
+ pin->mux_sel = args.args[0];
+
+ if (pin->mux_sel >= pin->mux->npads)
+ pin->mux_sel = pin->mux->select;
+
+ pin_id = fh_pinctrl_get_pin_id(group, j);
+ if (pin_id >= 0)
+ group->pin_ids[j] = pin_id;
+ else
+ return pin_id;
+
+ /* set the pin's reg config */
+ pad = &info->pin_pads[pin_id];
+ pin->config = pad->config;
+ func_idx = fh_pinctrl_find_func_in_pad(pin->name, pad);
+ if (func_idx < 0) {
+ dev_err(info->dev, "can not find func %s in %s",
+ pin->name, pad->name);
+ return func_idx;
+ }
+ pin->config.bit.mfs = func_idx;
+
+ dev_dbg(info->dev, "\tget pin %s --> mux_sel %d",
+ pin->name, pin->mux_sel);
+ }
+ }
+
+ return 0;
+}
+
+
+static int fh_pinctrl_probe_dt(struct platform_device *pdev,
+ struct fh_pinctrl_soc_info *info)
+{
+ static const char *FH_PINCTRL_GROUPS = "pinctrl_groups";
+ static const char *FH_PINCTRL_PAD = "pinpad";
+ static const char *FH_PINCTRL_MUX = "pinmux";
+
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *np_grp;
+ struct device_node *np_pad;
+ struct device_node *np_mux;
+ unsigned int nfuncs = 1;
+ bool flat_funcs;
+ int ret = 0;
+
+ if (!np)
+ return -ENODEV;
+
+ np_pad = of_get_child_by_name(np, FH_PINCTRL_PAD);
+ np_mux = of_get_child_by_name(np, FH_PINCTRL_MUX);
+ np_grp = of_get_child_by_name(np, FH_PINCTRL_GROUPS);
+
+ if (!np_grp || !np_pad || !np_mux) {
+ dev_err(&pdev->dev, "child node %s or %s or %s not found\n",
+ FH_PINCTRL_GROUPS, FH_PINCTRL_PAD, FH_PINCTRL_MUX);
+ return -ENODEV;
+ }
+
+ flat_funcs = fh_pinctrl_dt_is_flat_functions(np_grp);
+ if (flat_funcs) {
+ nfuncs = 1;
+ } else {
+ nfuncs = of_get_child_count(np_grp);
+ if (nfuncs <= 0) {
+ dev_err(&pdev->dev, "no functions defined\n");
+ return -EINVAL;
+ }
+ }
+
+ info->nfunctions = nfuncs;
+ PINCTRL_DEVM_KZALLOC_ARRAY(info->dev, info->functions, info->nfunctions);
+
+ ret = fh_pinctrl_parse_pinpads(np_pad, info);
+ if (ret) {
+ dev_err(&pdev->dev, "error when parse pinpads, ret: %d\n", ret);
+ return ret;
+ }
+
+ ret = fh_pinctrl_parse_pinmuxs(np_mux, info);
+ if (ret) {
+ dev_err(&pdev->dev, "error when parse pinmuxs, ret: %d\n", ret);
+ return ret;
+ }
+
+ ret = fh_pinctrl_parse_pingroups(np_grp, info);
+ if (ret) {
+ dev_err(&pdev->dev, "error when parse pingroups, ret: %d\n", ret);
+ return ret;
+ }
+
+
+ dev_info(&pdev->dev, "nfuncs: %d, ngroups: %d\n", nfuncs, info->ngroups);
+
+ return 0;
+}
+
+static int fh_pinctrl_procfile_init(void);
+
+static int fh_pinctrl_probe_with_info(struct platform_device *pdev,
+ struct fh_pinctrl_soc_info *info)
+{
+ struct device_node *dev_np = pdev->dev.of_node;
+ struct pinctrl_desc *fh_pinctrl_desc;
+ struct fh_pinctrl *fhpctl;
+ struct resource *res;
+ int ret, i;
+
+ info->dev = &pdev->dev;
+
+ PINCTRL_PARSE_PROPERTY_U32(dev_np, "pad-num", info->npins);
+
+ PINCTRL_PARSE_PROPERTY_U32(dev_np, "max-mux", info->max_mux);
+
+ info->pupd_enable = 1;
+ info->pupd_disable = 0;
+ info->pupd_zero = 0;
+
+ of_property_read_u32(dev_np, "pupd-enable", &info->pupd_enable);
+ of_property_read_u32(dev_np, "pupd-disable", &info->pupd_disable);
+ of_property_read_u32(dev_np, "pupd-zero", &info->pupd_zero);
+
+ dev_info(&pdev->dev, "%d pins, max-mux: %d\n", info->npins, info->max_mux);
+
+ /* Create state holders etc for this driver */
+ PINCTRL_DEVM_KZALLOC(&pdev->dev, fhpctl);
+
+ PINCTRL_DEVM_KZALLOC_ARRAY(&pdev->dev, info->pin_regs, info->npins);
+ PINCTRL_DEVM_KZALLOC_ARRAY(&pdev->dev, info->pin_pads, info->npins);
+ PINCTRL_DEVM_KZALLOC_ARRAY(&pdev->dev, info->pins, info->npins);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ info->pbase = (void *)res->start;
+ info->vbase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(info->vbase))
+ return PTR_ERR(info->vbase);
+
+ for (i = 0; i < info->npins; i++) {
+ info->pin_regs[i] = info->vbase + i * 4;
+ info->pins[i].number = i;
+ info->pin_pads[i].index = -1;
+ info->pin_pads[i].func_sel = -1;
+ info->pin_pads[i].reg = info->pin_regs[i];
+ }
+
+ PINCTRL_DEVM_KZALLOC(&pdev->dev, fh_pinctrl_desc);
+
+ fh_pinctrl_desc->name = dev_name(&pdev->dev);
+ fh_pinctrl_desc->pins = info->pins;
+ fh_pinctrl_desc->npins = info->npins;
+ fh_pinctrl_desc->pctlops = &fh_pinctrl_ops;
+ fh_pinctrl_desc->pmxops = &fh_pmx_ops;
+#ifdef CONFIG_PINCONF
+ fh_pinctrl_desc->confops = &fh_pinconf_ops;
+#endif
+ fh_pinctrl_desc->owner = THIS_MODULE;
+
+ ret = fh_pinctrl_probe_dt(pdev, info);
+ if (ret) {
+ dev_err(&pdev->dev, "fail to probe dt properties\n");
+ return ret;
+ }
+
+ fhpctl->info = info;
+ fhpctl->dev = info->dev;
+ platform_set_drvdata(pdev, fhpctl);
+ fhpctl->pctl = devm_pinctrl_register(&pdev->dev,
+ fh_pinctrl_desc, fhpctl);
+ if (IS_ERR(fhpctl->pctl)) {
+ dev_err(&pdev->dev, "could not register Fullhan pinctrl driver\n");
+ return PTR_ERR(fhpctl->pctl);
+ }
+
+ ret = fh_pinctrl_procfile_init();
+ if (ret)
+ return ret;
+
+ dev_info(&pdev->dev, "initialized Fullhan pinctrl driver\n");
+
+ return 0;
+}
+
+static struct fh_pinctrl_soc_info fh_pinctrl_info;
+
+static const struct of_device_id fh_pinctrl_of_match[] = {
+ { .compatible = "fh,fh-pinctrl", },
+ { /* sentinel */ }
+};
+
+static int fh_pinctrl_probe(struct platform_device *pdev)
+{
+ return fh_pinctrl_probe_with_info(pdev, &fh_pinctrl_info);
+}
+
+static struct platform_driver fh_pinctrl_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .of_match_table = of_match_ptr(fh_pinctrl_of_match),
+ },
+ .probe = fh_pinctrl_probe,
+};
+
+static int __init fh_pinctrl_init(void)
+{
+ return platform_driver_register(&fh_pinctrl_driver);
+}
+arch_initcall(fh_pinctrl_init);
+
+
+/* ----------------- pinctrl proc file api ---------------- */
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+
+
+static int fh_pmx_set_mux(const struct fh_pingroup *grp, const char *mux_name,
+ int muxsel, const struct fh_pinctrl_soc_info *info,
+ const char **oldfunc)
+{
+ struct fh_pinpad *pad;
+ int func_index = -1;
+ int i;
+
+ if (!grp || !mux_name || grp->npins == 0 || muxsel < 0)
+ return -EINVAL;
+
+ for (i = 0; i < grp->npins; i++) {
+ struct fh_pin *pin = &grp->pins[i];
+
+ if (strncmp(mux_name, pin->name, MAX_NAME_CHARS) == 0) {
+ if (muxsel >= pin->mux->npads) {
+ pr_err("[PINCTRL] set mux %s error, muxsel out of range\n",
+ mux_name);
+ return -EINVAL;
+ }
+
+ pin->mux_sel = muxsel;
+ pad = pin->mux->pads[muxsel];
+
+ func_index = fh_pinctrl_find_func_in_pad(mux_name, pad);
+ if (func_index < 0)
+ return func_index;
+ /* save oldfunc */
+ if (oldfunc) {
+ if (pad->func_sel >= 0
+ && pad->func_sel < pad->nfunc)
+ *oldfunc = pad->funcs[pad->func_sel];
+ else
+ *oldfunc = NULL;
+ }
+
+ pad->config = pin->config;
+ pad->config.bit.mfs = func_index;
+ if (pin->mux->ds >= 0)
+ pad->config.bit.ds = pin->mux->ds;
+ pin->mux->select = muxsel;
+
+ fh_pinctrl_check_duplicate_pin(pad->index, info);
+ fh_pinctrl_update_pad_reg(pad);
+
+ pr_debug("[PINCTRL] write pin reg: id %2d, offset 0x%03x, "
+ "val 0x%08x, %s\n",
+ pad->index, (int)pad->reg&0xfff, pad->config.dw, pin->name);
+ break;
+ }
+ }
+
+ if (func_index < 0) {
+ pr_err("[PINCTRL] pin %s of dev %s not found\n", mux_name, grp->name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int fh_pinctrl_smux(const char *dev, const char* mux, int muxsel, int flag)
+{
+ struct fh_pingroup *group;
+ const char *oldfunc = NULL;
+ int ret = 0;
+
+ if (flag & PIN_RESTORE) {
+ struct fh_pinpad *pad;
+ struct fh_pinmux *m = fh_pinctrl_find_mux_by_name(mux,
+ &fh_pinctrl_info);
+
+ if (m == NULL) {
+ pr_err("[PINCTRL] mux %s not found", mux);
+ return -ENOENT;
+ }
+
+ pad = m->pads[m->select];
+ pad->config.bit.mfs = fh_pinctrl_find_func_in_pad(mux, pad);
+ if (m->ds >= 0)
+ pad->config.bit.ds = m->ds;
+ fh_pinctrl_check_duplicate_pin(pad->index, &fh_pinctrl_info);
+ fh_pinctrl_update_pad_reg(pad);
+ return 0;
+ }
+
+ group = fh_pinctrl_find_group_by_name(&fh_pinctrl_info, dev);
+
+ if (!group) {
+ pr_err("[PINCTRL] device %s not found", dev);
+ return -ENODEV;
+ }
+
+ pr_info("[PINCTRL] %s: %s %d\n", dev, mux, muxsel);
+
+ ret = fh_pmx_set_mux(group, mux, muxsel, &fh_pinctrl_info, &oldfunc);
+ if (flag & PIN_BACKUP)
+ return (int)oldfunc;
+ else
+ return ret;
+}
+EXPORT_SYMBOL(fh_pinctrl_smux);
+
+char *fh_pinctrl_smux_backup(char *devname, char *muxname, int muxsel)
+{
+ return (char *)fh_pinctrl_smux(devname, muxname, muxsel, PIN_BACKUP);
+}
+EXPORT_SYMBOL(fh_pinctrl_smux_backup);
+
+char *fh_pinctrl_smux_restore(char *devname, char *muxname, int muxsel)
+{
+ return (char *)fh_pinctrl_smux(devname, muxname, muxsel, PIN_RESTORE);
+}
+EXPORT_SYMBOL(fh_pinctrl_smux_restore);
+
+int fh_pinctrl_sdev(const char *dev, int flag)
+{
+ struct fh_pingroup *group;
+
+ group = fh_pinctrl_find_group_by_name(&fh_pinctrl_info, dev);
+ if (!group) {
+ pr_err("[PINCTRL] device %s not found", dev);
+ return -ENODEV;
+ }
+
+ pr_info("[PINCTRL] %s\n", dev);
+
+ return fh_pmx_set_group(group, &fh_pinctrl_info);
+}
+EXPORT_SYMBOL(fh_pinctrl_sdev);
+
+static struct fh_pinpad *fh_pinctrl_get_pin_by_name(char *pin_name)
+{
+ struct fh_pinpad *pad;
+ const char *name;
+ int i;
+
+ for (i = 0; i < fh_pinctrl_info.npins; i++) {
+ pad = &fh_pinctrl_info.pin_pads[i];
+ if (!pad->funcs)
+ continue;
+ name = pad->funcs[pad->config.bit.mfs];
+ if (!strncmp(name, pin_name, MAX_NAME_CHARS))
+ return pad;
+ }
+
+ return NULL;
+}
+
+int fh_pinctrl_spupd(char *pin_name, unsigned int pupd)
+{
+ struct fh_pinpad *pad = NULL;
+ int ret;
+
+ pad = fh_pinctrl_get_pin_by_name(pin_name);
+
+ if (!pad) {
+ pr_err("ERROR: cannot find pin %s\n", pin_name);
+ return -ENXIO;
+ }
+
+ ret = fh_pinctrl_set_pin_pupd(&pad->config, pupd);
+ if (ret) {
+ pr_err("error config pupd:%d, ret: %d\n", pupd, ret);
+ return ret;
+ }
+
+ fh_pinctrl_update_pad_reg(pad);
+ return 0;
+}
+EXPORT_SYMBOL(fh_pinctrl_spupd);
+
+int fh_pinctrl_sds(char *pin_name, unsigned int ds)
+{
+ struct fh_pinpad *pad = NULL;
+
+ if (ds > 7) {
+ pr_err("ds val is in [0-7]\n");
+ return -EINVAL;
+ }
+
+ pad = fh_pinctrl_get_pin_by_name(pin_name);
+
+ if (!pad) {
+ pr_err("ERROR: cannot find pin %s\n", pin_name);
+ return -ENXIO;
+ }
+
+ pad->config.bit.ds = ds;
+
+ fh_pinctrl_update_pad_reg(pad);
+ return 0;
+}
+EXPORT_SYMBOL(fh_pinctrl_sds);
+
+int fh_pinctrl_set_oe(char *pin_name, unsigned int oe)
+{
+ struct fh_pinpad *pad = NULL;
+
+ if (oe > 1) {
+ pr_err("oe is 0 or 1\n");
+ return -EINVAL;
+ }
+
+ pad = fh_pinctrl_get_pin_by_name(pin_name);
+
+ if (!pad) {
+ pr_err("ERROR: cannot find pin %s\n", pin_name);
+ return -ENXIO;
+ }
+
+ pad->config.bit.oe = oe;
+
+ fh_pinctrl_update_pad_reg(pad);
+ return 0;
+}
+EXPORT_SYMBOL(fh_pinctrl_set_oe);
+
+static struct proc_dir_entry *pinctrl_proc_file;
+
+static void del_char(char* str,char ch)
+{
+ char *p = str;
+ char *q = str;
+ while(*q)
+ {
+ if (*q !=ch)
+ {
+ *p++ = *q;
+ }
+ q++;
+ }
+ *p='\0';
+}
+
+static ssize_t fh_pinctrl_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off)
+{
+ int i;
+ char message[32] = {0};
+ char * const delim = ",";
+ char *cur = message;
+ char* param_str[4];
+ unsigned long param[4];
+
+ len = (len > 32) ? 32 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for (i = 0; i < 4; i++)
+ {
+ param_str[i] = strsep(&cur, delim);
+ if(!param_str[i])
+ {
+ pr_err("%s: ERROR: parameter[%d] is empty\n", __func__, i);
+ pr_err("[dev/mux], [dev name], [mux name], [func sel]\n");
+ return -EINVAL;
+ }
+ else
+ {
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ }
+ }
+
+ if (!strcmp(param_str[0], "dev")) {
+ fh_pinctrl_sdev(param_str[1], 0);
+ }
+ else if (!strcmp(param_str[0], "mux")) {
+ int ret = (u32)kstrtoul(param_str[3], 10, &param[3]);
+
+ if (ret || param[3] < 0) {
+ pr_err("ERROR: parameter[3] is incorrect\n");
+ return -EINVAL;
+ }
+ fh_pinctrl_smux(param_str[1], param_str[2], param[3], 0);
+ } else if (!strcmp(param_str[0], "pupd")) {
+ if (!strcmp(param_str[2], "up"))
+ param[2] = PUPD_UP;
+ else if (!strcmp(param_str[2], "down"))
+ param[2] = PUPD_DOWN;
+ else if (!strcmp(param_str[2], "none"))
+ param[2] = PUPD_NONE;
+ else {
+ pr_err("usage pupd, [pin name], [up|down|none], 0");
+ return -EINVAL;
+ }
+ if (!fh_pinctrl_spupd(param_str[1], param[2]))
+ pr_info("PIN: %s pupd: %s\n", param_str[1],
+ param_str[2]);
+ } else if (!strcmp(param_str[0], "ds")) {
+ int ret = kstrtoul(param_str[2], 10, &param[2]);
+
+ if (ret || param[2] < 0) {
+ pr_err("usage: ds, [pin name] [ds_val(0~7)], 0\n");
+ return -EINVAL;
+ }
+ if (!fh_pinctrl_sds(param_str[1], param[2]))
+ pr_info("PIN: %s ds: %ld\n", param_str[1], param[2]);
+ } else {
+ pr_err("ERROR: parameter[0] is incorrect\n"
+ "[dev/mux], [dev name], [mux name], [func sel]\n");
+ return -EINVAL;
+ }
+
+ return len;
+}
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter = 0;
+ if (*pos == 0)
+ return &counter;
+ else
+ {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ struct fh_pinpad *pad;
+ int i;
+
+ fh_pinctrl_check_padlist(&fh_pinctrl_info);
+
+ seq_printf(sfile, "%2s\t%8s\t%6s\t%8s %4s%4s%4s%8s%4s\n",
+ "ID", "NAME", "ADDR", "REG", "SEL", "IE", "OE", "PUPD", "DS");
+ for (i = 0; i < fh_pinctrl_info.npins; i++) {
+ pad = &fh_pinctrl_info.pin_pads[i];
+ fh_pinctrl_print_pin_info(pad, sfile, 0);
+ if (pad->index >= 0)
+ seq_printf(sfile, "\n");
+ }
+ return 0;
+}
+
+static const struct seq_operations pinctrl_seq_ops =
+{
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_pinctrl_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &pinctrl_seq_ops);
+}
+
+static struct file_operations fh_pinctrl_proc_ops =
+{
+ .owner = THIS_MODULE,
+ .open = fh_pinctrl_proc_open,
+ .read = seq_read,
+ .write = fh_pinctrl_proc_write,
+ .release = seq_release,
+};
+
+static int fh_pinctrl_procfile_init(void)
+{
+ pinctrl_proc_file = proc_create(FH_PINCTRL_PROC_FILE, 0644, NULL ,
+ &fh_pinctrl_proc_ops);
+
+ if (!pinctrl_proc_file) {
+ pr_err("%s: ERROR: %s proc file create failed", __func__, DEVICE_NAME);
+ return -1;
+ }
+ return 0;
+}
+
+
+MODULE_AUTHOR("Fullhan");
+
+MODULE_DESCRIPTION("FH PINCTRL driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-fullhan.h b/drivers/pinctrl/pinctrl-fullhan.h
new file mode 100644
index 00000000..23dc5115
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-fullhan.h
@@ -0,0 +1,166 @@
+/*
+ * Core driver for Fullhan pin controller
+ *
+ * Copyright (C) 2018 Shanghai Fullhan Microelectronics Co., Ltd.
+ *
+ * Author: Wang Yuliang <wangyl307@fullhan.com>
+ *
+ */
+
+#ifndef __PINCTRL_FULLHAN_H
+#define __PINCTRL_FULLHAN_H
+
+#define DEVICE_NAME "fh_pinctrl"
+#define FH_PINCTRL_PROC_FILE "driver/pinctrl"
+
+struct platform_device;
+
+
+/**
+ * struct fh_pmx_func - describes pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @num_groups: the number of groups
+ */
+struct fh_pmx_func {
+ const char *name;
+ const char **groups;
+ unsigned num_groups;
+};
+
+
+typedef union {
+ struct {
+ unsigned int sl : 1; /*0*/
+ unsigned int : 3; /*1~3*/
+ unsigned int ds : 3; /*4~6*/
+ unsigned int msc : 1; /*7*/
+ unsigned int st : 1; /*8*/
+ unsigned int : 3; /*9~11*/
+ unsigned int ie : 1; /*12*/
+ unsigned int : 3; /*13~15*/
+ unsigned int pd : 1; /*16*/
+ unsigned int : 3; /*17~19*/
+ unsigned int pu : 1; /*20*/
+ unsigned int : 3; /*21~23*/
+ unsigned int mfs : 4; /*24~27*/
+ unsigned int oe : 1; /*28*/
+ unsigned int : 3; /*29~31*/
+ } bit;
+ unsigned int dw;
+} fh_pin_reg;
+
+struct fh_pinpad {
+ int index;
+ const char *name;
+ int nfunc;
+ int func_sel;
+ const char **funcs;
+ fh_pin_reg config; /* config[reg'val] of read from reg or write to reg */
+ fh_pin_reg *reg; /* real reg data, vaddr --> paddr: 0xf000000xx */
+};
+
+struct fh_pinmux {
+ const char *name;
+ unsigned int mux_id;
+ unsigned int select;
+ int ds;
+ unsigned int npads;
+ struct fh_pinpad **pads;
+};
+
+struct fh_pin {
+ const char *name;
+ unsigned int mux_sel;
+ fh_pin_reg config; /* the corresponding pinpad'config */
+ struct fh_pinmux *mux;
+};
+
+struct fh_pingroup {
+ const char *name;
+ unsigned npins;
+ unsigned *pin_ids;
+ struct fh_pin *pins;
+};
+
+struct fh_pinctrl_soc_info {
+ struct device *dev;
+ void *pbase;
+ void *vbase;
+ struct pinctrl_pin_desc *pins;
+ unsigned int npins;
+ unsigned int nmuxs;
+ unsigned int max_mux;
+ fh_pin_reg **pin_regs;
+ struct fh_pinpad *pin_pads;
+ struct fh_pinmux *pin_muxs;
+ struct fh_pingroup *pin_groups;
+ unsigned int ngroups;
+ struct fh_pmx_func *functions;
+ unsigned int nfunctions;
+ unsigned int flags;
+ unsigned int pupd_enable;
+ unsigned int pupd_disable;
+ unsigned int pupd_zero;
+};
+
+/**
+ * @dev: a pointer back to containing device
+ * @base: the offset to the controller in virtual memory
+ */
+struct fh_pinctrl {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ const struct fh_pinctrl_soc_info *info;
+};
+
+#define NEED_CHECK_PINLIST (1)
+#define PIN_BACKUP (1<<1)
+#define PIN_RESTORE (1<<2)
+
+#define PUPD_NONE (0)
+#define PUPD_UP (1)
+#define PUPD_DOWN (2)
+
+#define MAX_NAME_CHARS (32)
+#define PINCONFIG_MASK (0x0FFFFFFF)
+
+#ifndef SET_REG
+#define SET_REG(addr, val) writel(val, (void __iomem *)addr)
+#endif
+#ifndef GET_REG
+#define GET_REG(addr) readl((void __iomem *)addr)
+#endif
+
+
+#define PINCTRL_PARSE_PROPERTY_U32(np, pp, val) \
+ if (of_property_read_u32(np, pp, &val)) { \
+ dev_err(info->dev, "error when read property "pp" %s in L%d", \
+ np->full_name, __LINE__); \
+ return -EINVAL; \
+ }
+
+#define PINCTRL_DEVM_KZALLOC_ARRAY(dev, ptr, count) \
+ if ((int)count <= 0) \
+ dev_err(dev, "error "#count" : %d in L%d", count, __LINE__); \
+ ptr = devm_kzalloc(dev, sizeof(*ptr) * count, GFP_KERNEL); \
+ if (!ptr) \
+ return -ENOMEM;
+
+#define PINCTRL_DEVM_KZALLOC(dev, ptr) PINCTRL_DEVM_KZALLOC_ARRAY(dev, ptr, 1)
+
+#define PINCTRL_DEVM_KFREE(dev, ptr) devm_kfree(dev, ptr)
+
+// #define PINCTRL_DEBUG
+#if defined PINCTRL_DEBUG
+#undef dev_dbg
+#define dev_dbg dev_info
+#define DBG_LINE_ARGS(fmt, ...) printk(KERN_CRIT"%s L%d: "fmt"\n", \
+ __func__, __LINE__, __VA_ARGS__)
+#define DBG_LINE() printk(KERN_CRIT"%s L%d\n", __func__, __LINE__)
+#else
+#define DBG_LINE_ARGS(fmt, ...)
+#define DBG_LINE()
+#endif
+
+#endif /* __PINCTRL_FULLHAN_H */
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 02e46bbc..1a235fc8 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -89,6 +89,13 @@ config POWER_RESET_HISI
help
Reboot support for Hisilicon boards.
+config POWER_RESET_FH
+ bool "Fullhan power-off driver"
+ depends on ARCH_FULLHAN
+ help
+ Reboot support for Fullhan boards.
+
+
config POWER_RESET_IMX
bool "IMX6 power-off driver"
depends on POWER_RESET && SOC_IMX6
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 1be307c7..033bd0e3 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
+obj-$(CONFIG_POWER_RESET_FH) += fh-reboot.o
obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
diff --git a/drivers/power/reset/fh-reboot.c b/drivers/power/reset/fh-reboot.c
new file mode 100644
index 00000000..86f61edd
--- /dev/null
+++ b/drivers/power/reset/fh-reboot.c
@@ -0,0 +1,82 @@
+/*
+ * Hisilicon SoC reset code
+ *
+ * Copyright (c) 2018 Fullhan Ltd.
+ * Copyright (c) 2014 Linaro Ltd.
+ *
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/proc-fns.h>
+
+static void __iomem *base;
+static u32 reboot_offset;
+
+static int fh_restart_handler(struct notifier_block *this,
+ unsigned long mode, void *cmd)
+{
+ writel_relaxed(0x7fffffff, base + reboot_offset);
+
+ while (1)
+ cpu_do_idle();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block fh_restart_nb = {
+ .notifier_call = fh_restart_handler,
+ .priority = 128,
+};
+
+static int fh_reboot_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int err;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ WARN(1, "failed to map base address");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(np, "SWRST_MAIN_CTRL", &reboot_offset) < 0) {
+ pr_err("failed to find SWRST_MAIN_CTRL property\n");
+ iounmap(base);
+ return -EINVAL;
+ }
+
+ err = register_restart_handler(&fh_restart_nb);
+ if (err) {
+ dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n",
+ err);
+ iounmap(base);
+ }
+
+ return err;
+}
+
+static const struct of_device_id fh_reboot_of_match[] = {
+ { .compatible = "fh,fh-pmu" },
+ {}
+};
+
+static struct platform_driver fh_reboot_driver = {
+ .probe = fh_reboot_probe,
+ .driver = {
+ .name = "fh-reboot",
+ .of_match_table = fh_reboot_of_match,
+ },
+};
+module_platform_driver(fh_reboot_driver);
diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig
index 564a51ab..5b3566e2 100644
--- a/drivers/pps/Kconfig
+++ b/drivers/pps/Kconfig
@@ -31,7 +31,7 @@ config PPS_DEBUG
config NTP_PPS
bool "PPS kernel consumer support"
- depends on !NO_HZ_COMMON
+ depends on !NO_HZ_COMMON && NTP
help
This option adds support for direct in-kernel time
synchronization using an external PPS signal.
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index bf012889..cf3165f9 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -30,7 +30,60 @@ if PWM
config PWM_SYSFS
bool
- default y if SYSFS
+ default n
+
+config DEBUG_PWM_FS
+ bool
+ prompt "Enable PWM DEBUG Interface"
+ default n
+ depends on DEBUG_FS
+
+config PWM_FULLHAN
+ tristate "FH PWM support"
+ help
+ To compile this driver as a module, choose M here: the module will
+ be called fh_pwm.
+
+if PWM_FULLHAN
+if (ARCH_FH885xV200 || ARCH_FH865x)
+config FH_PWM_NUM
+ int
+ prompt "Number of PWMs, range: 1~14"
+ default 14
+ range 1 14
+ help
+ Number of PWMs
+endif
+
+if MACH_FH8626V100
+config FH_PWM_NUM
+ int
+ prompt "Number of PWMs, range: 1~14"
+ default 14
+ range 1 14
+ help
+ Number of PWMs
+
+config PWM_FULLHAN_V21
+ bool
+ default y
+endif
+
+if (MACH_FH8856 || MACH_FH8852)
+config FH_PWM_NUM
+ int
+ prompt "Number of PWMs, range: 1~8"
+ default 8
+ range 1 8
+ help
+ Number of PWMs
+
+config PWM_FULLHAN_V20
+ bool
+ default y
+endif
+
+endif
config PWM_AB8500
tristate "AB8500 PWM support"
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 1194c54e..1d7e5d83 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -46,3 +46,8 @@ obj-$(CONFIG_PWM_TIPWMSS) += pwm-tipwmss.o
obj-$(CONFIG_PWM_TWL) += pwm-twl.o
obj-$(CONFIG_PWM_TWL_LED) += pwm-twl-led.o
obj-$(CONFIG_PWM_VT8500) += pwm-vt8500.o
+obj-$(CONFIG_PWM_FULLHAN) += pwm-fullhan-common.o
+ifeq ($(CONFIG_ARCH_FH885xV200),y)
+ obj-$(CONFIG_PWM_FULLHAN) += pwmv3.o
+endif
+
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 172ef824..d8617ced 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -972,7 +972,7 @@ bool pwm_can_sleep(struct pwm_device *pwm)
}
EXPORT_SYMBOL_GPL(pwm_can_sleep);
-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_DEBUG_PWM_FS
static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
{
unsigned int i;
diff --git a/drivers/pwm/pwm-fullhan-common.c b/drivers/pwm/pwm-fullhan-common.c
new file mode 100644
index 00000000..03b322b4
--- /dev/null
+++ b/drivers/pwm/pwm-fullhan-common.c
@@ -0,0 +1,1038 @@
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <linux/printk.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/decompress/mm.h>
+#include <linux/of_address.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/fh_pwm.h>
+#include "pwm-fullhan-common.h"
+#include <mach/fh_pwm_plat.h>
+#include <mach/pmu.h>
+
+#define FH_PWM_DEBUG
+#ifdef FH_PWM_DEBUG
+#define PRINT_DBG(fmt, args...) printk(fmt, ##args)
+#else
+#define PRINT_DBG(fmt, args...) do {} while (0)
+#endif
+
+#define STATUS_INT (1<<31)
+#define STATUS_FINALL0 (1<<0)
+#define STATUS_FINALL1 (1<<1)
+#define STATUS_FINALL2 (1<<2)
+#define STATUS_FINALL3 (1<<3)
+#define STATUS_FINALL4 (1<<4)
+#define STATUS_FINALL5 (1<<5)
+#define STATUS_FINALL6 (1<<6)
+#define STATUS_FINALL7 (1<<7)
+#define STATUS_FINONCE0 (1<<8)
+#define STATUS_FINONCE1 (1<<9)
+#define STATUS_FINONCE2 (1<<10)
+#define STATUS_FINONCE3 (1<<11)
+#define STATUS_FINONCE4 (1<<12)
+#define STATUS_FINONCE5 (1<<13)
+#define STATUS_FINONCE6 (1<<14)
+#define STATUS_FINONCE7 (1<<15)
+
+#define OFFSET_PWM_BASE(n) (PWM_REG_INTERVAL + PWM_REG_INTERVAL * n)
+
+#define OFFSET_PWM_GLOBAL_CTRL0 (0x000)
+#define OFFSET_PWM_GLOBAL_CTRL1 (0x004)
+#define OFFSET_PWM_GLOBAL_CTRL2 (0x008)
+#define OFFSET_PWM_INT_ENABLE (0x010)
+#define OFFSET_PWM_INT_STATUS (0x014)
+
+#define OFFSET_PWM_CTRL(n) (0x000 + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_CFG0(n) (0x004 + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_CFG1(n) (0x008 + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_CFG2(n) (0x00c + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_CFG3(n) (0x010 + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_CFG4(n) (0x014 + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_STATUS0(n) (0x020 + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_STATUS1(n) (0x024 + OFFSET_PWM_BASE(n))
+#define OFFSET_PWM_STATUS2(n) (0x028 + OFFSET_PWM_BASE(n))
+
+struct pwm_chip_data {
+ struct fh_pwm_chip_data chip_data;
+ wait_queue_head_t wait_done;
+};
+
+struct fh_pwm_driver {
+ unsigned int irq;
+ struct pwm_chip chip;
+ void __iomem *base;
+ struct clk *clk;
+ struct proc_dir_entry *proc_file;
+};
+
+struct fh_pwm_driver *fh_pwm_drv;
+
+static void fh_pwm_output_mask(unsigned int mask)
+{
+ writel(mask, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2);
+}
+
+static void fh_pwm_output_enable(unsigned int n)
+{
+ unsigned int reg;
+
+ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2);
+ reg |= (1 << n);
+ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2);
+}
+
+static void fh_pwm_output_disable(unsigned int n)
+{
+ unsigned int reg;
+
+ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2);
+ reg &= ~(1 << n);
+ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2);
+}
+
+static void fh_pwm_config_enable(unsigned int n)
+{
+ unsigned int reg;
+
+ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0);
+ reg |= (1 << n);
+ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0);
+}
+
+static void fh_pwm_config_disable(unsigned int n)
+{
+ unsigned int reg;
+
+ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0);
+ reg &= ~(1 << n);
+ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0);
+}
+
+static void __attribute__((unused)) fh_pwm_shadow_enable(unsigned int n)
+{
+ unsigned int reg;
+
+ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1);
+ reg |= (1 << n);
+ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1);
+}
+
+static void __attribute__((unused)) fh_pwm_shadow_disable(unsigned int n)
+{
+ unsigned int reg;
+
+ reg = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1);
+ reg &= ~(1 << n);
+ writel(reg, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1);
+}
+
+static void fh_pwm_interrupt_finishall_enable(unsigned int n)
+{
+ void *base;
+
+ base = (void *)(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE);
+ _pwm_interrupt_finishall_enable(base, n);
+}
+
+static void fh_pwm_interrupt_finishall_disable(unsigned int n)
+{
+ void *base;
+
+ base = (void *)(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE);
+ _pwm_interrupt_finishall_disable(base, n);
+}
+
+static void fh_pwm_interrupt_finishonce_enable(unsigned int n)
+{
+ void *base;
+
+ base = (void *)(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE);
+ _pwm_interrupt_finishonce_enable(base, n);
+}
+
+static void fh_pwm_interrupt_finishonce_disable(unsigned int n)
+{
+ void *base;
+
+ base = (void *)(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE);
+ _pwm_interrupt_finishonce_disable(base, n);
+}
+
+static void fh_pwm_interrupt_finishonce_clear(unsigned int n)
+{
+ void *base;
+
+ base = (void *)(fh_pwm_drv->base + OFFSET_PWM_INT_STATUS);
+ _pwm_interrupt_finishonce_clear(base, n);
+}
+
+static void fh_pwm_interrupt_finishall_clear(unsigned int n)
+{
+ void *base;
+
+ base = (void *)(fh_pwm_drv->base + OFFSET_PWM_INT_STATUS);
+ _pwm_interrupt_finishall_clear(base, n);
+}
+
+static unsigned int fh_pwm_interrupt_get_status(void)
+{
+ unsigned int reg;
+
+ reg = readl(fh_pwm_drv->base + OFFSET_PWM_INT_STATUS);
+ reg &= readl(fh_pwm_drv->base + OFFSET_PWM_INT_ENABLE);
+
+ return reg;
+}
+
+static void fh_pwm_get_status(struct fh_pwm_chip_data *chip_data)
+{
+ unsigned int status0, status1, status2;
+
+ status0 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS0(chip_data->id));
+ status1 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS1(chip_data->id));
+ status2 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS2(chip_data->id));
+ chip_data->status.busy = (status2 >> 4) & 0x1;
+ chip_data->status.error = (status2 >> 3) & 0x1;
+ chip_data->status.total_cnt = status1;
+ chip_data->status.done_cnt = status0;
+}
+
+static int fh_pwm_wait_done(struct pwm_chip_data *pcd)
+{
+ struct fh_pwm_chip_data *chip_data = &pcd->chip_data;
+
+ if (chip_data)
+ fh_pwm_get_status(chip_data);
+
+ if (chip_data->status.busy == 0)
+ return chip_data->status.done_cnt;
+
+ if (chip_data->config.finish_all)
+ wait_event_interruptible(pcd->wait_done, chip_data->status.busy == 0);
+ else {
+ while (chip_data->status.busy == 1) {
+ mdelay(10);
+ fh_pwm_get_status(chip_data);
+ }
+ }
+ return chip_data->status.done_cnt;
+}
+
+static int fh_pwm_set_config(struct fh_pwm_chip_data *chip_data)
+{
+ unsigned int clk_rate = clk_get_rate(fh_pwm_drv->clk);
+ unsigned int ctrl = 0, period, duty, delay, phase, reg;
+ unsigned int inverse = 0;
+
+ fh_pwm_config_disable(chip_data->id);
+
+ period = chip_data->config.period_ns / (NSEC_PER_SEC / clk_rate);
+ duty = chip_data->config.duty_ns / (NSEC_PER_SEC / clk_rate);
+ delay = chip_data->config.delay_ns / (NSEC_PER_SEC / clk_rate);
+ phase = chip_data->config.phase_ns / (NSEC_PER_SEC / clk_rate);
+
+ if (period > 0x1ffffff) {
+ pr_err("PWM: period exceed 24-bit\n");
+ return -EINVAL;
+ }
+
+ if (period == 0x0) {
+ pr_err("PWM: period too low\n");
+ return -EINVAL;
+ }
+
+ if (duty > 0x1ffffff) {
+ pr_err("PWM: duty exceed 24-bit\n");
+ return -EINVAL;
+ }
+
+ if (duty > period) {
+ pr_err("PWM: duty is over period\n");
+ return -EINVAL;
+ }
+
+ /* Calculate Inverse */
+ if ((phase + duty) > period) {
+ if (_pwm_need_inverse()) {
+ phase = phase % period;
+ phase = phase + duty - period;
+ duty = period - duty;
+ inverse = 1;
+ }
+ }
+
+ PRINT_DBG("set period: 0x%x\n", period);
+ PRINT_DBG("set duty: 0x%x\n", duty);
+ PRINT_DBG("set phase: 0x%x\n", phase);
+ PRINT_DBG("set delay: 0x%x\n", delay);
+
+ writel(period, fh_pwm_drv->base + OFFSET_PWM_CFG0(chip_data->id));
+ writel(duty, fh_pwm_drv->base + OFFSET_PWM_CFG1(chip_data->id));
+ writel(phase, fh_pwm_drv->base + OFFSET_PWM_CFG2(chip_data->id));
+ writel(delay, fh_pwm_drv->base + OFFSET_PWM_CFG3(chip_data->id));
+ writel(chip_data->config.pulses,
+ fh_pwm_drv->base + OFFSET_PWM_CFG4(chip_data->id));
+
+ if (chip_data->config.delay_ns)
+ ctrl |= 1 << 3;
+
+ if (!chip_data->config.pulses)
+ ctrl |= 1 << 0;
+
+ ctrl |= (chip_data->config.stop & 0x3) << 1;
+
+ ctrl |= inverse << 4;
+
+ writel(ctrl, fh_pwm_drv->base + OFFSET_PWM_CTRL(chip_data->id));
+
+ PRINT_DBG("set ctrl: 0x%x\n", ctrl);
+
+ ctrl = readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1);
+
+ reg = (chip_data->config.stop >> 4) & 0x1;
+ if (reg)
+ ctrl |= _pwm_set_stoptime_bit(chip_data->id);
+ else
+ ctrl &= _pwm_set_stoptime_bit(chip_data->id);
+
+ writel(ctrl, fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1);
+
+ writel(chip_data->config.pulses,
+ fh_pwm_drv->base + OFFSET_PWM_CFG4(chip_data->id));
+ PRINT_DBG("set pulses: 0x%x\n", chip_data->config.pulses);
+
+ if (chip_data->config.finish_once)
+ fh_pwm_interrupt_finishonce_enable(chip_data->id);
+ else
+ fh_pwm_interrupt_finishonce_disable(chip_data->id);
+
+ if (chip_data->config.finish_all) {
+ struct pwm_chip_data *pcd;
+
+ pcd = pwm_get_chip_data(&fh_pwm_drv->chip.pwms[chip_data->id]);
+ init_waitqueue_head(&pcd->wait_done);
+ fh_pwm_interrupt_finishall_enable(chip_data->id);
+ } else
+ fh_pwm_interrupt_finishall_disable(chip_data->id);
+
+ fh_pwm_config_enable(chip_data->id);
+
+ return 0;
+}
+
+static void fh_pwm_get_config(struct fh_pwm_chip_data *chip_data)
+{
+ unsigned int clk_rate = clk_get_rate(fh_pwm_drv->clk);
+ unsigned int ctrl = 0, period, duty, delay, phase, pulses,
+ status0, status1, status2;
+
+ period = readl(fh_pwm_drv->base + OFFSET_PWM_CFG0(chip_data->id));
+ duty = readl(fh_pwm_drv->base + OFFSET_PWM_CFG1(chip_data->id));
+ phase = readl(fh_pwm_drv->base + OFFSET_PWM_CFG2(chip_data->id));
+ delay = readl(fh_pwm_drv->base + OFFSET_PWM_CFG3(chip_data->id));
+ pulses = readl(fh_pwm_drv->base + OFFSET_PWM_CFG4(chip_data->id));
+ ctrl = readl(fh_pwm_drv->base + OFFSET_PWM_CTRL(chip_data->id));
+ status0 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS0(chip_data->id));
+ status1 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS1(chip_data->id));
+ status2 = readl(fh_pwm_drv->base + OFFSET_PWM_STATUS2(chip_data->id));
+
+
+ PRINT_DBG("==============================\n");
+ PRINT_DBG("pwm%d register config:\n", chip_data->id);
+ PRINT_DBG("\t\tperiod: 0x%x\n", period);
+ PRINT_DBG("\t\tduty: 0x%x\n", duty);
+ PRINT_DBG("\t\tphase: 0x%x\n", phase);
+ PRINT_DBG("\t\tdelay: 0x%x\n", delay);
+ PRINT_DBG("\t\tpulses: 0x%x\n", pulses);
+ PRINT_DBG("\t\tctrl: 0x%x\n", ctrl);
+ PRINT_DBG("\t\tstatus0: 0x%x\n", status0);
+ PRINT_DBG("\t\tstatus1: 0x%x\n", status1);
+ PRINT_DBG("\t\tstatus2: 0x%x\n", status2);
+
+ chip_data->config.period_ns = period * (NSEC_PER_SEC / clk_rate);
+ chip_data->config.duty_ns = duty * (NSEC_PER_SEC / clk_rate);
+
+ PRINT_DBG("\t\tclk_rate: %d\n", clk_rate);
+ PRINT_DBG("\t\tconfig.period_ns: %d\n", chip_data->config.period_ns);
+ PRINT_DBG("\t\tconfig.duty_ns: %d\n", chip_data->config.duty_ns);
+ PRINT_DBG("==============================\n\n");
+
+ chip_data->config.phase_ns = phase * (NSEC_PER_SEC / clk_rate);
+ chip_data->config.delay_ns = delay * (NSEC_PER_SEC / clk_rate);
+ chip_data->config.pulses = pulses;
+ chip_data->config.stop = (ctrl >> 1) & 0x3;
+ chip_data->config.percent = chip_data->config.duty_ns /
+ (chip_data->config.period_ns / 100);
+
+ chip_data->status.busy = (status2 >> 4) & 0x1;
+ chip_data->status.error = (status2 >> 3) & 0x1;
+ chip_data->status.total_cnt = status1;
+ chip_data->status.done_cnt = status0;
+}
+
+int fh_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct fh_pwm_chip_data *chip_data;
+
+ chip_data = kzalloc(sizeof(struct fh_pwm_chip_data), GFP_KERNEL);
+ if (chip_data == NULL) {
+ pr_err("pwm[%d], chip data malloc failed\n", pwm->hwpwm);
+ return -ENOMEM;
+ }
+
+ chip_data->id = pwm->hwpwm;
+ chip_data->config.duty_ns = duty_ns;
+ chip_data->config.period_ns = period_ns;
+
+ fh_pwm_set_config(chip_data);
+
+ kfree(chip_data);
+
+ return 0;
+}
+
+int fh_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ fh_pwm_output_enable(pwm->hwpwm);
+ return 0;
+}
+
+void fh_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ fh_pwm_output_disable(pwm->hwpwm);
+}
+
+static int fh_pwm_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_pwm_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+static long fh_pwm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ struct fh_pwm_chip_data chip_data = {0};
+ unsigned int val;
+
+ if (unlikely(_IOC_TYPE(cmd) != PWM_IOCTL_MAGIC)) {
+ pr_err("%s: ERROR: incorrect magic num %d (error: %d)\n",
+ __func__, _IOC_TYPE(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+
+ if (unlikely(_IOC_NR(cmd) > PWM_IOCTL_MAXNR)) {
+ pr_err("%s: ERROR: incorrect cmd num %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -ENOTTY);
+ return -ENOTTY;
+ }
+
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ ret = !access_ok(VERIFY_WRITE,
+ (void __user *)arg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ ret = !access_ok(VERIFY_READ,
+ (void __user *)arg, _IOC_SIZE(cmd));
+
+ if (ret) {
+ pr_err("%s: ERROR: user space access is not permitted %d (error: %d)\n",
+ __func__, _IOC_NR(cmd), -EACCES);
+ return -EACCES;
+ }
+
+ switch (cmd) {
+ case SET_PWM_ENABLE:
+ get_user(val, (unsigned int __user *)arg);
+ fh_pwm_output_enable(val);
+ break;
+ case ENABLE_PWM:
+ ret = copy_from_user((void *)&chip_data,
+ (void __user *)arg,
+ sizeof(struct fh_pwm_chip_data));
+ if (ret != 0) {
+ pr_err("ioctrl:Get chip data from user space failed\n");
+ return -EFAULT;
+ }
+
+ if (chip_data.id >= fh_pwm_drv->chip.npwm) {
+ pr_err("ioctrl:PWM Channel Error\n");
+ return -EFAULT;
+ }
+
+ memcpy(
+ fh_pwm_drv->chip.pwms[chip_data.id].chip_data,
+ (void *)&chip_data,
+ sizeof(struct fh_pwm_chip_data));
+
+ fh_pwm_output_enable(chip_data.id);
+ break;
+ case DISABLE_PWM:
+ ret = copy_from_user((void *)&chip_data,
+ (void __user *)arg,
+ sizeof(struct fh_pwm_chip_data));
+ if (ret != 0) {
+ pr_err("ioctrl:Get chip data from user space failed\n");
+ return -EFAULT;
+ }
+
+ if (chip_data.id >= fh_pwm_drv->chip.npwm) {
+ pr_err("ioctrl:PWM Channel Error\n");
+ return -EFAULT;
+ }
+
+ memcpy(
+ fh_pwm_drv->chip.pwms[chip_data.id].chip_data,
+ (void *)&chip_data,
+ sizeof(struct fh_pwm_chip_data));
+
+ fh_pwm_output_disable(chip_data.id);
+ break;
+ case SET_PWM_DUTY_CYCLE:
+ ret = copy_from_user((void *)&chip_data,
+ (void __user *)arg,
+ sizeof(struct fh_pwm_chip_data));
+ if (ret != 0) {
+ pr_err("ioctrl:Get chip data from user space failed\n");
+ return -EFAULT;
+ }
+
+ if (chip_data.id >= fh_pwm_drv->chip.npwm) {
+ pr_err("ioctrl:PWM Channel Error\n");
+ return -EFAULT;
+ }
+
+ memcpy(
+ fh_pwm_drv->chip.pwms[chip_data.id].chip_data,
+ (void *)&chip_data,
+ sizeof(struct fh_pwm_chip_data));
+ pr_info("ioctl: SET_PWM_DUTY_CYCLE, "
+ "pwm->id: %d, pwm->counter: %d, pwm->period: %d ns\n",
+ chip_data.id, chip_data.config.duty_ns,
+ chip_data.config.period_ns);
+
+ ret = fh_pwm_set_config(&chip_data);
+ break;
+ case GET_PWM_DUTY_CYCLE:
+ ret = copy_from_user((void *)&chip_data,
+ (void __user *)arg,
+ sizeof(struct fh_pwm_chip_data));
+ if (ret != 0) {
+ pr_err("ioctrl:Get chip data from user space failed\n");
+ return -EFAULT;
+ }
+ if (chip_data.id >= fh_pwm_drv->chip.npwm) {
+ pr_err("ioctrl:PWM Channel Error\n");
+ return -EFAULT;
+ }
+ memcpy(
+ fh_pwm_drv->chip.pwms[chip_data.id].chip_data,
+ (void *)&chip_data,
+ sizeof(struct fh_pwm_chip_data));
+ pr_info("ioctl: GET_PWM_DUTY_CYCLE, "
+ "pwm->id: %d, pwm->counter: %d, pwm->period: %d ns\n",
+ chip_data.id, chip_data.config.duty_ns,
+ chip_data.config.period_ns);
+ fh_pwm_get_config(&chip_data);
+ ret = copy_to_user((void __user *)arg,
+ (void *)&chip_data,
+ sizeof(struct fh_pwm_chip_data));
+ if (ret != 0) {
+ pr_err("ioctrl:Copy chip data to user space failed\n");
+ return -EFAULT;
+ }
+ break;
+ case SET_PWM_DUTY_CYCLE_PERCENT:
+ ret = copy_from_user((void *)&chip_data,
+ (void __user *)arg,
+ sizeof(struct fh_pwm_chip_data));
+ if (ret != 0) {
+ pr_err("Get chip data from user space failed\n");
+ return -EFAULT;
+ }
+
+ if (chip_data.id >= fh_pwm_drv->chip.npwm) {
+ pr_err("ioctrl:PWM Channel Error\n");
+ return -EFAULT;
+ }
+ if (chip_data.config.percent > 100) {
+ pr_err("ERROR: percentage is over 100\n");
+ return -EIO;
+ }
+ chip_data.config.duty_ns = chip_data.config.period_ns *
+ chip_data.config.percent / 100;
+ memcpy(
+ fh_pwm_drv->chip.pwms[chip_data.id].chip_data,
+ (void *)&chip_data,
+ sizeof(struct fh_pwm_chip_data));
+ pr_info("ioctl: SET_PWM_DUTY_CYCLE_PERCENT, "
+ "pwm->id: %d, pwm->counter: %d, pwm->period: %d ns\n",
+ chip_data.id, chip_data.config.duty_ns,
+ chip_data.config.period_ns);
+ ret = fh_pwm_set_config(&chip_data);
+ break;
+ case ENABLE_MUL_PWM:
+ get_user(val, (unsigned int __user *)arg);
+ fh_pwm_output_mask(val);
+ break;
+ case ENABLE_FINSHALL_INTR:
+ get_user(val, (unsigned int __user *)arg);
+ fh_pwm_interrupt_finishall_enable(val);
+ break;
+ case ENABLE_FINSHONCE_INTR:
+ get_user(val, (unsigned int __user *)arg);
+ fh_pwm_interrupt_finishonce_enable(val);
+ break;
+ case DISABLE_FINSHALL_INTR:
+ get_user(val, (unsigned int __user *)arg);
+ fh_pwm_interrupt_finishall_disable(val);
+ break;
+ case DISABLE_FINSHONCE_INTR:
+ get_user(val, (unsigned int __user *)arg);
+ fh_pwm_interrupt_finishonce_disable(val);
+ break;
+ case WAIT_PWM_FINSHALL:
+ get_user(val, (unsigned int __user *)arg);
+ ret = fh_pwm_wait_done(fh_pwm_drv->chip.pwms[val].chip_data);
+ break;
+ }
+
+ return ret;
+}
+
+static const struct file_operations fh_pwm_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_pwm_open,
+ .release = fh_pwm_release,
+ .unlocked_ioctl = fh_pwm_ioctl,
+};
+
+static struct miscdevice fh_pwm_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_NAME,
+ .fops = &fh_pwm_fops,
+};
+
+static const struct pwm_ops fh_pwm_ops = {
+ .config = fh_pwm_config,
+ .enable = fh_pwm_enable,
+ .disable = fh_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+
+static void del_char(char *str, char ch)
+{
+ char *p = str;
+ char *q = str;
+
+ while (*q) {
+ if (*q != ch)
+ *p++ = *q;
+ q++;
+ }
+ *p = '\0';
+}
+
+static ssize_t fh_pwm_proc_write(struct file *filp, const char *buf, size_t len, loff_t *off)
+{
+ int i;
+ char message[64] = {0};
+ char *const delim = ",";
+ char *cur = message;
+ char *param_str[8];
+ unsigned int param[8] = {0};
+ struct fh_pwm_chip_data *chip_data;
+
+ len = (len > 64) ? 64 : len;
+
+ if (copy_from_user(message, buf, len))
+ return -EFAULT;
+
+ for (i = 0; i < 8; i++) {
+ param_str[i] = strsep(&cur, delim);
+ if (!param_str[i]) {
+ pr_err("%s: ERROR: parameter[%d] is empty\n",
+ __func__, i);
+ pr_err("id, switch_mask, duty_ns, period_ns, "
+ "numofpules, delay_ns, phase_ns, stop_status\n");
+ pr_err("eg. echo '0,1,5000,10000,0,0,1000,0' > /proc/driver/pwm\n");
+ return -EINVAL;
+ } else {
+ del_char(param_str[i], ' ');
+ del_char(param_str[i], '\n');
+ param[i] = (unsigned int)simple_strtoul(param_str[i], NULL, 10);
+ if (param[i] < 0) {
+ pr_err("%s: ERROR: parameter[%d] is incorrect\n", __func__, i);
+ pr_err("id, switch_mask, duty_ns, period_ns, numofpules, "
+ "delay_ns, phase_ns, stop_status\n");
+ pr_err("eg. echo '0,1,5000,10000,0,0,1000,0' > /proc/driver/pwm\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ chip_data = kzalloc(sizeof(struct fh_pwm_chip_data), GFP_KERNEL);
+ if (chip_data == NULL) {
+ pr_err("pwm[%d], chip data malloc failed\n", i);
+ return 0;
+ }
+
+ chip_data->id = param[0];
+ chip_data->config.duty_ns = param[2];
+ chip_data->config.period_ns = param[3];
+ chip_data->config.pulses = param[4];
+ chip_data->config.delay_ns = param[5];
+ chip_data->config.phase_ns = param[6];
+ chip_data->config.stop = param[7];
+
+
+ fh_pwm_set_config(chip_data);
+
+ printk("set pwm %d, enable: 0x%x, duty cycle: %u ns, period cycle: %u,"
+ "numofpulse: %d, delay: %d ns, phase: %d ns, stop: %d\n",
+ param[0], param[1], param[2], param[3],
+ param[4], param[5], param[6], param[7]);
+
+ fh_pwm_output_mask(param[1]);
+
+ kfree(chip_data);
+
+ return len;
+}
+
+static void *v_seq_start(struct seq_file *s, loff_t *pos)
+{
+ static unsigned long counter;
+
+ if (*pos == 0)
+ return &counter;
+ else {
+ *pos = 0;
+ return NULL;
+ }
+}
+
+static void *v_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void v_seq_stop(struct seq_file *s, void *v)
+{
+
+}
+
+static int v_seq_show(struct seq_file *sfile, void *v)
+{
+ int i;
+
+ seq_printf(sfile, "\nPWM Status:\n");
+ seq_printf(sfile, "global_ctrl0: 0x%x\n",
+ readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL0));
+ seq_printf(sfile, "global_ctrl1: 0x%x\n",
+ readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL1));
+ seq_printf(sfile, "global_ctrl2: 0x%x\n",
+ readl(fh_pwm_drv->base + OFFSET_PWM_GLOBAL_CTRL2));
+
+ for (i = 0; i < fh_pwm_drv->chip.npwm; i++) {
+ struct pwm_chip_data *pcd;
+ struct fh_pwm_chip_data *chip_data;
+
+ pcd = pwm_get_chip_data(&fh_pwm_drv->chip.pwms[i]);
+ chip_data = &pcd->chip_data;
+ fh_pwm_get_config(chip_data);
+
+ seq_printf(sfile, "id: %d \t%s, duty_ns: %u, period_ns: %u\n",
+ chip_data->id,
+ (chip_data->status.busy) ? "ENABLE" : "DISABLE",
+ chip_data->config.duty_ns,
+ chip_data->config.period_ns);
+ }
+ return 0;
+}
+
+static const struct seq_operations pwm_seq_ops = {
+ .start = v_seq_start,
+ .next = v_seq_next,
+ .stop = v_seq_stop,
+ .show = v_seq_show
+};
+
+static int fh_pwm_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &pwm_seq_ops);
+}
+
+
+static const struct file_operations fh_pwm_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = fh_pwm_proc_open,
+ .read = seq_read,
+ .write = fh_pwm_proc_write,
+ .release = seq_release,
+};
+
+static irqreturn_t fh_pwm_interrupt(int this_irq, void *param)
+{
+ unsigned int status;
+ unsigned int chn_once = 0xFFFFFFFF;
+ unsigned int chn_all = 0xFFFFFFFF;
+ struct pwm_chip_data *pcd;
+
+ status = fh_pwm_interrupt_get_status();
+ _pwm_interrupt_process(status, &chn_once, &chn_all);
+
+ if (chn_once != 0xFFFFFFFF)
+ fh_pwm_interrupt_finishonce_clear(chn_once);
+
+ if (chn_all != 0xFFFFFFFF) {
+ struct pwm_chip chip = fh_pwm_drv->chip;
+ pcd = pwm_get_chip_data(&chip.pwms[chn_all]);
+ fh_pwm_get_status(&pcd->chip_data);
+ wake_up_interruptible(&pcd->wait_done);
+ fh_pwm_interrupt_finishall_clear(chn_all);
+ }
+
+ return IRQ_HANDLED;
+}
+#ifdef CONFIG_USE_OF
+static struct of_device_id const fh_pwm_of_match[] = {
+ { .compatible = "fh,fh-pwm" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fh_pwm_of_match);
+#endif
+
+static int fh_pwm_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ int i;
+#ifdef CONFIG_USE_OF
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *res;
+ struct fh_pwm_data *plat_data;
+#endif
+
+ fh_pwm_drv = kzalloc(sizeof(struct fh_pwm_driver), GFP_KERNEL);
+#ifdef CONFIG_USE_OF
+ match = of_match_device(fh_pwm_of_match, &pdev->dev);
+ if (!match) {
+ pr_info("failed to find pwm controller\n");
+ return -ENODEV;
+ }
+
+ fh_pwm_drv->base = of_iomap(np, 0);
+ if (fh_pwm_drv->base == NULL) {
+ err = -ENXIO;
+ goto done;
+ }
+
+ fh_pwm_drv->irq = irq_of_parse_and_map(np, 0);
+ if (fh_pwm_drv->irq < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ goto release_region;
+ }
+
+ err = request_irq(fh_pwm_drv->irq,
+ fh_pwm_interrupt, IRQF_NO_THREAD, "pwm", fh_pwm_drv);
+ if (err) {
+ dev_err(&pdev->dev, "failure requesting irq %i\n", fh_pwm_drv->irq);
+ goto release_irqmapping;
+ }
+
+ of_property_read_u32(np, "npwm", &fh_pwm_drv->chip.npwm);
+#else
+ plat_data = pdev->dev.platform_data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ err = -ENXIO;
+ goto done;
+ }
+
+ res = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (res == NULL) {
+ err = -EBUSY;
+ goto done;
+ }
+
+ fh_pwm_drv->base = ioremap(res->start, resource_size(res));
+ if (fh_pwm_drv->base == NULL) {
+ err = -ENXIO;
+ goto done;
+ }
+
+ fh_pwm_drv->irq = irq_create_mapping(NULL, platform_get_irq(pdev, 0));
+ if (fh_pwm_drv->irq < 0) {
+ err = -ENXIO;
+ dev_err(&pdev->dev, "no irq resource?\n");
+ goto release_region;
+ }
+
+ err = request_irq(fh_pwm_drv->irq,
+ fh_pwm_interrupt, IRQF_NO_THREAD,
+ "pwm", fh_pwm_drv);
+ if (err) {
+ err = -ENXIO;
+ dev_err(&pdev->dev, "failure requesting irq %i\n", fh_pwm_drv->irq);
+ goto release_irqmapping;
+ }
+
+ fh_pwm_drv->chip.npwm = plat_data->npwm;
+#endif
+
+ fh_pwm_drv->clk = clk_get(NULL, "pwm_clk");
+
+ if (IS_ERR(fh_pwm_drv->clk)) {
+ err = PTR_ERR(fh_pwm_drv->clk);
+ goto release_irq;
+ }
+
+ clk_prepare_enable(fh_pwm_drv->clk);
+
+ PRINT_DBG("%s: clk_rate: %lu\n", __func__, clk_get_rate(fh_pwm_drv->clk));
+
+ err = misc_register(&fh_pwm_misc);
+ if (err < 0) {
+ pr_err("%s: ERROR: %s registration failed",
+ __func__, DEVICE_NAME);
+ goto release_irq;
+ }
+
+ fh_pwm_drv->chip.dev = &pdev->dev;
+ fh_pwm_drv->chip.ops = &fh_pwm_ops;
+ fh_pwm_drv->chip.base = pdev->id;
+
+ err = pwmchip_add(&fh_pwm_drv->chip);
+ if (err < 0) {
+ pr_err("%s: ERROR: %s pwmchip_add failed",
+ __func__, DEVICE_NAME);
+ goto release_irq;
+ }
+
+ for (i = 0; i < fh_pwm_drv->chip.npwm; i++) {
+ struct pwm_chip_data *pcd;
+
+ pcd = kzalloc(sizeof(struct pwm_chip_data),
+ GFP_KERNEL);
+ if (pcd == NULL) {
+ pr_err("pwm[%d], chip data malloc failed\n", i);
+ continue;
+ }
+ pcd->chip_data.id = i;
+ pwm_set_chip_data(&fh_pwm_drv->chip.pwms[i], pcd);
+ }
+
+ platform_set_drvdata(pdev, fh_pwm_drv);
+
+ pr_info("PWM driver, Number: %d, IO base addr: 0x%p\n",
+ fh_pwm_drv->chip.npwm, fh_pwm_drv->base);
+
+ fh_pwm_drv->proc_file = proc_create(FH_PWM_PROC_FILE, S_IRUGO,
+ NULL, &fh_pwm_proc_ops);
+ if (!fh_pwm_drv->proc_file)
+ pr_err("%s: ERROR: %s proc file create failed",
+ __func__, DEVICE_NAME);
+
+ dev_dbg(&pdev->dev, "PWM probe successful, IO base addr: %p\n",
+ fh_pwm_drv->base);
+
+ return 0;
+
+release_irq:
+ free_irq(fh_pwm_drv->irq, fh_pwm_drv);
+release_irqmapping:
+ irq_dispose_mapping(fh_pwm_drv->irq);
+release_region:
+ iounmap(fh_pwm_drv->base);
+done:
+ kfree(fh_pwm_drv);
+
+ return err;
+}
+
+static int __exit fh_pwm_remove(struct platform_device *pdev)
+{
+ int err, i;
+ struct fh_pwm_driver *fh_pwm_drv = platform_get_drvdata(pdev);
+ proc_remove(fh_pwm_drv->proc_file);
+
+ for (i = 0; i < fh_pwm_drv->chip.npwm; i++)
+ kfree(fh_pwm_drv->chip.pwms[i].chip_data);
+
+ err = pwmchip_remove(&fh_pwm_drv->chip);
+ if (err < 0)
+ return err;
+
+ dev_dbg(&pdev->dev, "pwm driver removed\n");
+
+ clk_disable_unprepare(fh_pwm_drv->clk);
+ free_irq(fh_pwm_drv->irq, NULL);
+ iounmap(fh_pwm_drv->base);
+ platform_set_drvdata(pdev, NULL);
+ misc_deregister(&fh_pwm_misc);
+
+ free(fh_pwm_drv);
+ fh_pwm_drv = NULL;
+
+ return 0;
+}
+
+static struct platform_driver fh_pwm_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_USE_OF
+ .of_match_table = fh_pwm_of_match,
+#endif
+ },
+ .probe = fh_pwm_probe,
+ .remove = __exit_p(fh_pwm_remove),
+};
+
+static int __init fh_pwm_init(void)
+{
+ return platform_driver_register(&fh_pwm_driver);
+}
+
+static void __exit fh_pwm_exit(void)
+{
+
+ platform_driver_unregister(&fh_pwm_driver);
+
+}
+
+module_init(fh_pwm_init);
+module_exit(fh_pwm_exit);
+
+
+MODULE_AUTHOR("fullhan");
+
+MODULE_DESCRIPTION("Fullhan PWM device driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
diff --git a/drivers/pwm/pwm-fullhan-common.h b/drivers/pwm/pwm-fullhan-common.h
new file mode 100644
index 00000000..815b8626
--- /dev/null
+++ b/drivers/pwm/pwm-fullhan-common.h
@@ -0,0 +1,22 @@
+#ifndef _PWM_FULLHAN_COMMON_H_
+#define _PWM_FULLHAN_COMMON_H_
+
+#if defined(CONFIG_ARCH_FH885xV200) || \
+ defined(CONFIG_ARCH_FH865x) || \
+ defined(CONFIG_ARCH_FH8636) || \
+ defined(CONFIG_ARCH_FH8852V101)
+#define PWM_REG_INTERVAL (0x80)
+#else
+#define PWM_REG_INTERVAL (0x100)
+#endif
+unsigned int _pwm_set_stoptime_bit(int chn);
+void _pwm_interrupt_finishall_enable(void *base, int chn);
+void _pwm_interrupt_finishall_disable(void *base, int chn);
+void _pwm_interrupt_finishonce_enable(void *base, int chn);
+void _pwm_interrupt_finishonce_disable(void *base, int chn);
+void _pwm_interrupt_finishall_clear(void *base, int chn);
+void _pwm_interrupt_finishonce_clear(void *base, int chn);
+int _pwm_need_inverse(void);
+void _pwm_interrupt_process(unsigned int status, int *chn_once, int *chn_all);
+
+#endif /* _PWM_FULLHAN_COMMON_H_ */
diff --git a/drivers/pwm/pwmv1.c b/drivers/pwm/pwmv1.c
new file mode 100644
index 00000000..3e4adfac
--- /dev/null
+++ b/drivers/pwm/pwmv1.c
@@ -0,0 +1,79 @@
+#include <linux/io.h>
+#include "pwm-fullhan-common.h"
+
+unsigned int _pwm_set_stoptime_bit(int chn)
+{
+ return (0x1 << (8 + chn));
+}
+
+void _pwm_interrupt_finishall_enable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg |= (0x1 << chn);
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishall_disable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg &= ~(0x1 << chn);
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_enable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg |= (0x1 << (8 + chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_disable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg &= ~(0x1 << (8 + chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_clear(void *base, int chn)
+{
+ unsigned int reg = 0x0;
+
+ reg = readl(base);
+ reg &= ~(0x1 << (8 + chn));
+ return writel(reg, base);
+}
+
+void _pwm_interrupt_finishall_clear(void *base, int chn)
+{
+ unsigned int reg = 0x0;
+
+ reg = readl(base);
+ reg &= ~(0x1 << chn);
+ return writel(reg, base);
+}
+
+int _pwm_need_inverse(void)
+{
+ return 0;
+}
+
+void _pwm_interrupt_process(unsigned int status, int *chn_once, int *chn_all)
+{
+ unsigned int stat_once, stat_all;
+
+ status &= 0xffff;
+ stat_once = (status >> 8) & 0xffff;
+ stat_all = status & 0xffff;
+ if (stat_once)
+ *chn_once = fls(stat_once) - 1;
+ if (stat_all)
+ *chn_all = fls(stat_all) - 1;
+}
diff --git a/drivers/pwm/pwmv2.c b/drivers/pwm/pwmv2.c
new file mode 100644
index 00000000..845911b3
--- /dev/null
+++ b/drivers/pwm/pwmv2.c
@@ -0,0 +1,94 @@
+#include <linux/io.h>
+#include "pwm-fullhan-common.h"
+
+#define OFFSET_PWM_STOPTIME_BIT(n) (8 + 16 * ((n) / 8) + ((n) % 8))
+#define OFFSET_PWM_FINSHALL_BIT(n) (0 + 16 * ((n) / 8) + ((n) % 8))
+#define OFFSET_PWM_FINSHONCE_BIT(n) (8 + 16 * ((n) / 8) + ((n) % 8))
+
+unsigned int _pwm_set_stoptime_bit(int chn)
+{
+ return (0x1 << OFFSET_PWM_STOPTIME_BIT(chn));
+}
+
+void _pwm_interrupt_finishall_enable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg |= (0x1 << OFFSET_PWM_FINSHALL_BIT(chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishall_disable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg &= ~(0x1 << OFFSET_PWM_FINSHALL_BIT(chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_enable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg |= (0x1 << OFFSET_PWM_FINSHONCE_BIT(chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_disable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg &= ~(0x1 << OFFSET_PWM_FINSHONCE_BIT(chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_clear(void *base, int chn)
+{
+ unsigned int reg = 0x0;
+
+ reg = readl(base);
+ reg |= (0x1 << OFFSET_PWM_FINSHONCE_BIT(chn));
+ return writel(reg, base);
+}
+
+void _pwm_interrupt_finishall_clear(void *base, int chn)
+{
+ unsigned int reg = 0x0;
+
+ reg = readl(base);
+ reg |= (0x1 << OFFSET_PWM_FINSHALL_BIT(chn));
+ return writel(reg, base);
+}
+
+int _pwm_need_inverse(void)
+{
+ return 0;
+}
+
+void _pwm_interrupt_process(unsigned int status, int *chn_once, int *chn_all)
+{
+ unsigned int stat_once_l, stat_all_l;
+ unsigned int stat_once_h, stat_all_h;
+
+ status &= 0xffffffff;
+ stat_once_l = (status >> 8) & 0xff;
+ stat_all_l = status & 0xff;
+ stat_once_h = (status >> 24) & 0x3f;
+ stat_all_h = (status >> 16) & 0x3f;
+
+ if (stat_once_l)
+ *chn_once = fls(stat_once_l) - 1;
+ if (stat_all_l)
+ *chn_all = fls(stat_all_l) - 1;
+ /* Special Process: Data will be covered but not a bug
+ * Wait for next interrupt to process low interrupt.
+ */
+ if (stat_once_h)
+ *chn_once = fls(stat_once_h) + 8 - 1;
+ if (stat_all_h)
+ *chn_all = fls(stat_all_h) + 8 - 1;
+}
diff --git a/drivers/pwm/pwmv3.c b/drivers/pwm/pwmv3.c
new file mode 100644
index 00000000..1e678f8b
--- /dev/null
+++ b/drivers/pwm/pwmv3.c
@@ -0,0 +1,79 @@
+#include <linux/io.h>
+#include "pwm-fullhan-common.h"
+
+unsigned int _pwm_set_stoptime_bit(int chn)
+{
+ return (0x1 << (16 + chn));
+}
+
+void _pwm_interrupt_finishall_enable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg |= (0x1 << chn);
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishall_disable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg &= ~(0x1 << chn);
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_enable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg |= (0x1 << (16 + chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_disable(void *base, int chn)
+{
+ unsigned int reg;
+
+ reg = readl(base);
+ reg &= ~(0x1 << (16 + chn));
+ writel(reg, base);
+}
+
+void _pwm_interrupt_finishonce_clear(void *base, int chn)
+{
+ unsigned int reg = 0x0;
+
+ reg = readl(base);
+ reg &= ~(0x1 << (16 + chn));
+ return writel(reg, base);
+}
+
+void _pwm_interrupt_finishall_clear(void *base, int chn)
+{
+ unsigned int reg = 0x0;
+
+ reg = readl(base);
+ reg &= ~(0x1 << chn);
+ return writel(reg, base);
+}
+
+int _pwm_need_inverse(void)
+{
+ return 1;
+}
+
+void _pwm_interrupt_process(unsigned int status, int *chn_once, int *chn_all)
+{
+ unsigned int stat_once, stat_all;
+
+ status &= 0xffffffff;
+ stat_once = (status >> 16) & 0xffff;
+ stat_all = status & 0xffff;
+ if (stat_once)
+ *chn_once = fls(stat_once) - 1;
+ if (stat_all)
+ *chn_all = fls(stat_all) - 1;
+}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 0723c97e..0b6772ef 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -770,11 +770,7 @@ endif # SPI_MASTER
#
config RTC_I2C_AND_SPI
tristate
- default m if I2C=m
- default y if I2C=y
- default y if SPI_MASTER=y
- select REGMAP_I2C if I2C
- select REGMAP_SPI if SPI_MASTER
+ default n
comment "SPI and I2C RTC drivers"
@@ -1706,6 +1702,24 @@ config RTC_DRV_PIC32
This driver can also be built as a module. If so, the module
will be called rtc-pic32
+config RTC_DRV_FH
+ tristate "FH On-Chip RTC"
+ depends on RTC_CLASS
+ help
+ Say Y here to enable support for the on-chip RTC found in
+ FH processors.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-fh.
+if RTC_DRV_FH
+ config USE_TSENSOR
+ bool 'USE TSENSOR'
+ default n
+
+ config USE_TSENSOR_OFFSET
+ bool 'USE ENHANCEMENT TSENSOR'
+ default n
+endif
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 1ac694a3..afdb0bc0 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -165,3 +165,4 @@ obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o
obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o
+obj-$(CONFIG_RTC_DRV_FH) += rtc-fh_v2.o
diff --git a/drivers/rtc/rtc-fh_v2.c b/drivers/rtc/rtc-fh_v2.c
new file mode 100644
index 00000000..67f81e30
--- /dev/null
+++ b/drivers/rtc/rtc-fh_v2.c
@@ -0,0 +1,1361 @@
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/clk.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/workqueue.h>
+#include <linux/miscdevice.h>
+#include <linux/fh_rtc_v2.h>
+#ifdef CONFIG_USE_OF
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#else
+#include <linux/irqdomain.h>
+#endif
+#include <mach/pmu.h>
+#include <linux/fh_efuse.h>
+#include <mach/fh_rtc_plat.h>
+
+/*
+ * Registers offset
+ */
+#define FH_RTC_INT_STATUS 0x0
+#define FH_RTC_INT_EN 0x4
+#define FH_RTC_DEBUG0 0x8
+#define FH_RTC_DEBUG1 0xC
+#define FH_RTC_DEBUG2 0x10
+#define FH_RTC_CMD 0x14
+#define FH_RTC_RD_DATA 0x18
+#define FH_RTC_WR_DATA 0x1C
+
+#define FH_RTC_CMD_COUNTER (0<<4)
+#define FH_RTC_CMD_OFFSET (1<<4)
+#define FH_RTC_CMD_ALARM_CFG (2<<4)
+#define FH_RTC_CMD_TEMP_INFO (0x3<<4)
+#define FH_RTC_CMD_TEMP_CFG (0x4<<4)
+#define FH_RTC_CMD_ANA_CFG (0x5<<4)
+#define FH_RTC_CMD_INT_STATUS (0x6<<4)
+#define FH_RTC_CMD_INT_EN (0x7<<4)
+#define FH_RTC_CMD_DEBUG (0x8<<4)
+#define FH_RTC_CMD_OFFSET_LUT (0x9<<4)
+
+#define OFFSET_EN (1<<0)
+#define OFFSET_ATUTO (1<<1)
+#define OFFSET_IDX (1<<2)
+#define OFFSET_BK_EN (1<<8)
+#define OFFSET_BK_AUTO (1<<9)
+#define OFFSET_BK_IDX (1<<10)
+#define OFFSET_CURRENT (1<<16)
+#define LP_MODE (1<<31)
+
+#define RTC_READ 1
+#define RTC_WRITE 2
+#define RTC_TEMP 3
+#define FH_RTC_INT_STATUS_RX_CRC_ERR (1<<0)
+#define FH_RTC_INT_STATUS_RX_COM_ERR (1<<1)
+#define FH_RTC_INT_STATUS_RX_LEN_ERR (1<<2)
+#define FH_RTC_INT_STATUS_CNT_THL (1<<3)
+#define FH_RTC_INT_STATUS_CNT_THH (1<<4)
+#define FH_RTC_INT_STATUS_CORE_IDLE (1<<5)
+#define FH_RTC_INT_STATUS_CORE (1<<6)
+#define FH_RTC_INT_STATUS_WRAPPER_BUSY (1<<8)
+#define FH_RTC_INT_STATUS_CORE_BUSY (1<<16)
+
+#define FH_RTC_INT_RX_CRC_ERR_EN (1<<0)
+#define FH_RTC_INT_RX_COM_ERR_EN (1<<1)
+#define FH_RTC_INT_RX_LEN_ERR_EN (1<<2)
+#define FH_RTC_INT_CNT_THL_ERR_EN (1<<3)
+#define FH_RTC_INT_CNT_THH_ERR_EN (1<<4)
+#define FH_RTC_INT_CORE_IDLE_ERR_EN (1<<5)
+#define FH_RTC_INT_CORE_INT_ERR_EN (1<<6)
+#define FH_RTC_INT_RX_CRC_ERR_MASK (1<<16)
+#define FH_RTC_INT_RX_COM_ERR_MASK (1<<17)
+#define FH_RTC_INT_RX_LEN_ERR_MASK (1<<18)
+#define FH_RTC_INT_CNT_THL_ERR_MASK (1<<19)
+#define FH_RTC_INT_CNT_THH_ERR_MASK (1<<20)
+#define FH_RTC_INT_CORE_IDLE_ERR_MASK (1<<21)
+#define FH_RTC_INT_CORE_INT_ERR_MASK (1<<22)
+#define FH_RTC_INT_CORE_INT_ERR_MASK_COV 0xffbfffff
+#define FH_RTC_INT_CORE_INT_STATUS_COV 0xffffff3f
+#define FH_RTC_INT_CORE_INT_ALL_COV 0xffffffff
+
+#define FH_RTC_CORE_INT_EN_SEC_INT (0x1<<0)
+#define FH_RTC_CORE_INT_EN_MIN_INT (0x1<<1)
+#define FH_RTC_CORE_INT_EN_HOU_INT (0x1<<2)
+#define FH_RTC_CORE_INT_EN_DAY_INT (0x1<<3)
+#define FH_RTC_CORE_INT_EN_ALM_INT (0x1<<4)
+#define FH_RTC_CORE_INT_EN_POW_INT (0x1<<5)
+
+
+#define FH_RTC_CORE_INT_EN_SEC_MAS (0x1<<16)
+#define FH_RTC_CORE_INT_EN_MIN_MAS (0x1<<17)
+#define FH_RTC_CORE_INT_EN_HOU_MAS (0x1<<18)
+#define FH_RTC_CORE_INT_EN_DAY_MAS (0x1<<19)
+#define FH_RTC_CORE_INT_EN_ALM_MAS (0x1<<20)
+#define FH_RTC_CORE_INT_EN_POE_MAS (0x1<<21)
+
+/* #define FH_RTC_DEBUG_PRINT */
+
+#ifdef FH_RTC_DEBUG_PRINT
+#define RTC_PRINT_DBG(fmt, args...) \
+ do {
+ pr_info("[FH_RTC_DEBUG]: ");
+ printk(fmt, ## args)
+ } while (0)
+#else
+#define RTC_PRINT_DBG(fmt, args...) do { } while (0)
+#endif
+
+#ifdef CONFIG_USE_TSENSOR
+#define USE_TSENSOR
+
+#ifdef CONFIG_USE_TSENSOR_OFFSET
+#define USE_TSENSOR_OFFSET
+#endif
+
+#endif
+
+struct fh_rtc_controller {
+ void * __iomem regs;
+ unsigned int v_addr;
+ unsigned int irq;
+ unsigned int paddr;
+ unsigned int base_year;
+ unsigned int base_month;
+ unsigned int base_day;
+ struct rtc_device *rtc;
+ struct clk *clk;
+ int sadc_channel;
+
+ struct workqueue_struct *wq;
+ struct delayed_work self_adjust;
+ int tsensor_delta_val;
+ struct fh_rtc_plat_data *plat_data;
+};
+struct fh_rtc_core_int_status {
+ unsigned int core_int_en;
+ unsigned int core_int_status;
+};
+static struct fh_rtc_controller *fh_rtc;
+struct fh_rtc_core_int_status fh_core_int;
+enum {
+
+ TIME_FUNC = 0, ALARM_FUNC,
+
+};
+#ifdef USE_TSENSOR
+
+unsigned int TSENSOR_LUT[12] = {0x1b1e2023,
+ 0x11131618,
+ 0x090b0d0f,
+ 0x03040607,
+ 0x00010202,
+ 0x01000000,
+ 0x04030201,
+ 0x0b090706,
+ 0x1713100e,
+ 0x27221e1a,
+ 0x3e37322c,
+ 0x5b534c44};
+#endif
+
+
+
+static int fh_rtc_get_core(unsigned int base_addr, unsigned int reg_num);
+#ifdef USE_TSENSOR_OFFSET
+
+int tsensor_adjust_lut(void)
+{
+ unsigned int tsensor_init_data;
+ unsigned int tsensor_12bit;
+ int temp_diff;
+ int tsensor_out_value_diff;
+ int lut_cof = fh_rtc->plat_data->lut_cof;
+#if defined(CONFIG_ARCH_FH885xV200) || \
+defined(CONFIG_ARCH_FH865x)
+ tsensor_init_data = fh_pmu_get_tsensor_init_data();
+#else
+ unsigned int low_data, high_data;
+
+ low_data = efuse_read_debug_entry(60);
+ high_data = efuse_read_debug_entry(61);
+ tsensor_init_data = (high_data<<8)|low_data;
+#endif
+ tsensor_12bit = tsensor_init_data&0xfff;
+ tsensor_out_value_diff = tsensor_12bit
+ - fh_rtc->plat_data->tsensor_cp_default_out;
+ fh_rtc->tsensor_delta_val = tsensor_out_value_diff;
+
+ temp_diff = tsensor_out_value_diff*lut_cof/4096;
+
+ return temp_diff;
+}
+#endif
+#ifdef USE_TSENSOR
+static int fh_rtc_temp_cfg_coef_offset(unsigned int coef, unsigned int offset);
+static int fh_rtc_temp_cfg_thl_thh(unsigned int thl, unsigned int thh);
+#endif
+static int fh_rtc_set_core(unsigned int base_addr, unsigned int reg_num,
+ unsigned int value);
+#ifdef USE_TSENSOR
+static void rtc_adjust(void)
+{
+ int i;
+ int offset_index;
+ struct fh_rtc_plat_data *pd = fh_rtc->plat_data;
+
+ char offset_lut[48];
+
+ for (i = 0; i < 12; i++)
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_OFFSET_LUT+(i<<4),
+ TSENSOR_LUT[i]);
+
+ memcpy(offset_lut, TSENSOR_LUT, sizeof(offset_lut));
+
+ offset_index = 0;
+ for (i = 0; i < 46; i++) {
+ if (offset_lut[i] > offset_lut[i+1])
+ offset_index = i + 1;
+ else
+ offset_lut[i+1] = offset_lut[i];
+ }
+
+#ifdef USE_TSENSOR_OFFSET
+ i = tsensor_adjust_lut();
+ if ((i < 0) || (i > 5))
+ i = 0;
+ fh_rtc_temp_cfg_coef_offset(pd->lut_cof, pd->lut_offset-i);
+ pr_info("tsensor diff value : %d\n", i);
+#else
+ fh_rtc_temp_cfg_coef_offset(pd->lut_cof, pd->lut_offset);
+#endif
+ fh_rtc_temp_cfg_thl_thh(0, 47);
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_OFFSET,
+ (offset_index<<2) | (offset_index<<10)|
+ OFFSET_BK_EN|OFFSET_BK_AUTO);
+}
+#endif
+
+static inline void rtc_udelay(int us)
+{
+#ifdef CONFIG_HIGH_RES_TIMERS
+ usleep_range(us, us+20);
+#else
+ udelay(us);
+#endif
+}
+
+static int fh_rtc_core_idle(unsigned int base_addr)
+{
+ unsigned int status;
+
+ status = readl(fh_rtc->regs+FH_RTC_INT_STATUS);
+ if (status & FH_RTC_INT_STATUS_CORE_IDLE)
+ return 0;
+ else
+ return -1;
+}
+
+static int fh_rtc_core_wr(unsigned int base_addr)
+{
+ int reg;
+
+ reg = readl(fh_rtc->regs+FH_RTC_INT_STATUS);
+ reg &= (~FH_RTC_INT_STATUS_CORE_IDLE);
+ writel(reg, fh_rtc->regs+FH_RTC_INT_STATUS);
+
+ return 0;
+}
+
+static int fh_rtc_get_time(unsigned int base_addr)
+{
+
+ int reg, count, status;
+
+ status = fh_rtc_core_idle(base_addr);
+ if (status < 0) {
+ pr_info("fh rtc get time error %x\n", status);
+ return -1;
+ }
+ fh_rtc_core_wr(base_addr);
+ writel(RTC_READ, fh_rtc->regs+FH_RTC_CMD);
+ for (count = 0; count < 250; count++) {
+ status = fh_rtc_core_idle(base_addr);
+ if (status == 0) {
+ reg = readl((void * __iomem)base_addr+FH_RTC_RD_DATA);
+ return reg;
+ }
+ rtc_udelay(100);
+
+ }
+ pr_info("rtc core busy can't get time\n");
+
+ return -1;
+}
+
+static int fh_rtc_set_core(unsigned int base_addr, unsigned int reg_num,
+ unsigned int value)
+{
+ int count, status;
+
+ if (fh_rtc_core_idle(base_addr) < 0) {
+ pr_info("rtc get time:rtc core busy\n");
+ return -1;
+ }
+ fh_rtc_core_wr(base_addr);
+
+ writel(value, (void * __iomem)base_addr+FH_RTC_WR_DATA);
+ writel(reg_num|RTC_WRITE, (void * __iomem)base_addr+FH_RTC_CMD);
+ for (count = 0; count < 25; count++) {
+ status = fh_rtc_core_idle(base_addr);
+ if (status == 0)
+ return 0;
+
+ mdelay(1);
+
+ }
+ pr_info("rtc SET CORE REG TIMEOUT\n");
+
+ return -1;
+}
+
+static int fh_rtc_get_core(unsigned int base_addr, unsigned int reg_num)
+{
+ int reg, count, status;
+
+ if (fh_rtc_core_idle(base_addr) < 0) {
+ pr_err("rtc get time:rtc core busy %d\n", __LINE__);
+ return -1;
+ }
+ fh_rtc_core_wr(base_addr);
+ writel(reg_num|RTC_READ, (void * __iomem)base_addr+FH_RTC_CMD);
+ for (count = 0; count < 150; count++) {
+ status = fh_rtc_core_idle(base_addr);
+ if (status == 0) {
+ reg = readl((void * __iomem)base_addr+FH_RTC_RD_DATA);
+ return reg;
+ }
+ rtc_udelay(100);
+
+ }
+ pr_info("rtc GET CORE REG TIMEOUT line %d\n", __LINE__);
+
+ return -1;
+}
+
+#if defined(CONFIG_MACH_FH8856) || defined(CONFIG_MACH_FH8852)
+static int fh_rtc_get_temp(unsigned int base_addr)
+{
+ return 0;
+}
+#else
+static int fh_rtc_get_temp(unsigned int base_addr)
+{
+ int reg, count, status;
+
+ if (fh_rtc_core_idle(base_addr) < 0) {
+ pr_info("rtc get time:rtc core busy %d\n", __LINE__);
+ return -1;
+ }
+ fh_rtc_core_wr(base_addr);
+ writel(RTC_TEMP, (void * __iomem)base_addr+FH_RTC_CMD);
+ for (count = 0; count < 150; count++) {
+ status = fh_rtc_core_idle(base_addr);
+ if (status == 0) {
+ reg = readl((void * __iomem)base_addr+FH_RTC_RD_DATA);
+ return reg;
+ }
+ rtc_udelay(100);
+
+ }
+ pr_err("rtc GET CORE REG TIMEOUT line %d\n", __LINE__);
+
+ return -1;
+}
+#endif
+
+/* the temp[out] is 10 times of actually temperature */
+int fh_rtc_get_tsensor_data(int *data, int *temp)
+{
+ struct fh_rtc_plat_data *pd = fh_rtc->plat_data;
+ int raw_data = -1, t, status, count;
+ int offset = (signed char)pd->lut_offset;
+
+ fh_rtc_get_temp(fh_rtc->v_addr);
+
+ if (fh_rtc_core_idle(fh_rtc->v_addr) < 0) {
+ pr_err("rtc get time:rtc core busy %d\n", __LINE__);
+ return -1;
+ }
+ fh_rtc_core_wr(fh_rtc->v_addr);
+ writel(FH_RTC_CMD_TEMP_INFO|RTC_READ,
+ (void * __iomem)fh_rtc->v_addr+FH_RTC_CMD);
+ for (count = 0; count < 30; count++) {
+ status = fh_rtc_core_idle(fh_rtc->v_addr);
+ if (status == 0) {
+ raw_data = readl((void * __iomem)
+ fh_rtc->v_addr+FH_RTC_RD_DATA);
+ break;
+ }
+ mdelay(1);
+ }
+
+ if (raw_data < 0)
+ return raw_data;
+
+ if (data)
+ *data = raw_data;
+ raw_data += fh_rtc->tsensor_delta_val;
+ /* data * COF >> 12 + OFFSET = lut_index
+ * = (temp - (-50)) * 47 / (120 - (-50))
+ */
+ t = (raw_data * pd->lut_cof * 10 / 4096 + offset * 10) * 170 / 47 - 500;
+ if (temp)
+ *temp = t;
+ return 0;
+}
+EXPORT_SYMBOL(fh_rtc_get_tsensor_data);
+
+static int fh_rtc_set_time(unsigned int base_addr, unsigned int value)
+{
+ int count;
+
+ if (fh_rtc_core_idle(base_addr) < 0) {
+ pr_err("set time :rtc core busy\n");
+ return -1;
+ }
+ fh_rtc_core_wr(base_addr);
+ writel(value, (void * __iomem)base_addr+FH_RTC_WR_DATA);
+ writel(RTC_WRITE, (void * __iomem)base_addr+FH_RTC_CMD);
+ for (count = 0; count < 150; count++) {
+ if (fh_rtc_core_idle(base_addr) == 0)
+ return 0;
+ rtc_udelay(100);
+ }
+ pr_err("rtc core busy can't set time\n");
+
+ return -1;
+}
+#ifdef DRIVER_TEST
+static int fh_rtc_set_time_first(unsigned int base_addr, unsigned int value)
+{
+
+ writel(value, base_addr+FH_RTC_WR_DATA);
+ writel(RTC_WRITE, base_addr+FH_RTC_CMD);
+
+}
+#endif
+
+static int fh_rtc_alarm_enable_interrupt(unsigned int base_addr)
+{
+ int status;
+
+ status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ status & (~FH_RTC_ISR_ALARM_POS));
+
+ status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN);
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN,
+ (status | FH_RTC_CORE_INT_EN_ALM_INT));
+
+ status = readl((void *)fh_rtc->v_addr+FH_RTC_INT_STATUS);
+ writel(status & (~FH_RTC_INT_STATUS_CORE),
+ (void *)fh_rtc->v_addr+FH_RTC_INT_STATUS);
+
+ status = readl((void *)fh_rtc->v_addr+FH_RTC_INT_EN);
+ writel(status & (~FH_RTC_INT_CORE_INT_ERR_MASK),
+ (void *)fh_rtc->v_addr+FH_RTC_INT_EN);
+ return 0;
+}
+
+static int fh_rtc_alarm_disable_interrupt(unsigned int base_addr,
+ unsigned int value)
+{
+ int rtc_core_status;
+
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN);
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN, (rtc_core_status & (~FH_RTC_CORE_INT_EN_ALM_INT)));
+
+ return 0;
+}
+static int fh_rtc_set_alarm_time(unsigned int base_addr, unsigned int value)
+{
+ int status;
+
+#ifdef USE_DEBUG_REGISTER
+ int rtc_core_status, cys_count;
+
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_COUNTER);
+ if (rtc_core_status > value) {
+ pr_info("alarm time > now time\n");
+ return -ETIME;
+ }
+#endif
+ status = fh_rtc_set_core(base_addr,
+ FH_RTC_CMD_ALARM_CFG, value);
+ if (status < 0) {
+ pr_info("set alarm time failed\n");
+
+ return -1;
+ }
+#ifdef USE_DEBUG_REGISTER
+ if (rtc_core_status == value) {
+ cys_count = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_DEBUG);
+ if (cys_count > 0x3e00)
+ return -ETIME;
+ }
+#endif
+ return 0;
+}
+
+static int fh_rtc_get_alarm_time(unsigned int base_addr)
+{
+ int data;
+
+ data = fh_rtc_get_core(base_addr, FH_RTC_CMD_ALARM_CFG);
+
+ return data;
+}
+static unsigned int fh_rtc_get_hw_sec_data(unsigned int func_switch)
+{
+
+ unsigned int ret_sec, raw_value, sec_value;
+ unsigned int min_value, hour_value, day_value;
+
+ if (func_switch == TIME_FUNC)
+ raw_value = fh_rtc_get_time((unsigned int)fh_rtc->regs);
+ else
+ raw_value = fh_rtc_get_alarm_time((unsigned int)fh_rtc->regs);
+
+ sec_value = FH_GET_RTC_SEC(raw_value);
+ min_value = FH_GET_RTC_MIN(raw_value);
+ hour_value = FH_GET_RTC_HOUR(raw_value);
+ day_value = FH_GET_RTC_DAY(raw_value);
+ ret_sec = (day_value * 86400) + (hour_value * 3600) + (min_value * 60)
+ + sec_value;
+
+ return ret_sec;
+}
+
+#ifdef DRIVER_TEST
+#define TEMP_DATA 0x203
+static unsigned int fh_rtc_get_tmp(void)
+{
+ unsigned int value;
+
+ value = GET_REG((unsigned int)fh_rtc->regs + FH_RTC_CMD_TEMP_INFO);
+
+ return value;
+}
+static void fh_rtc_tmp_en(void)
+{
+ fh_rtc_set_core((unsigned int)fh_rtc->regs, FH_RTC_CMD_OFFSET,
+ TEMP_DATA);
+}
+#endif
+static int fh_rtc_set_hw_sec_data(struct rtc_time *rtc_tm,
+ unsigned int func_switch)
+{
+ unsigned int raw_value, sec_value, min_value;
+ unsigned int hour_value, day_value;
+ unsigned long now;
+ int status;
+
+ if (func_switch == ALARM_FUNC) {
+ rtc_tm_to_time(rtc_tm, &now);
+ now--;
+ rtc_time_to_tm(now, rtc_tm);
+ }
+
+ day_value = rtc_year_days(rtc_tm->tm_mday, rtc_tm->tm_mon,
+ rtc_tm->tm_year + 1900);
+ day_value += (rtc_tm->tm_year - 70)
+ * 365 + ELAPSED_LEAP_YEARS(rtc_tm->tm_year);
+
+ hour_value = rtc_tm->tm_hour;
+ min_value = rtc_tm->tm_min;
+ sec_value = rtc_tm->tm_sec;
+
+ raw_value = (day_value << DAY_BIT_START) |
+ (hour_value << HOUR_BIT_START)
+ | (min_value << MIN_BIT_START) |
+ (sec_value << SEC_BIT_START);
+
+ if (func_switch == TIME_FUNC) {
+ status = fh_rtc_set_time((unsigned int)fh_rtc->regs, raw_value);
+ } else {
+ status = fh_rtc_set_alarm_time((unsigned int)fh_rtc->regs,
+ raw_value);
+ }
+ return status;
+}
+
+static int fh_rtc_open(struct device *dev)
+{
+ return 0;
+}
+
+static void fh_rtc_release(struct device *dev)
+{
+}
+
+#ifdef DRIVER_TEST
+static int fh_rtc_tm_compare(struct rtc_time *tm0, struct rtc_time *tm1)
+{
+ unsigned long read = 0, write = 0;
+
+ rtc_tm_to_time(tm0, &read);
+ rtc_tm_to_time(tm1, &write);
+
+ if (write > read || write < read - 2) {
+ RTC_PRINT_DBG(
+ "ERROR: read(%d-%d-%d %d:%d:%d) vs write(%d-%d-%d %d:%d:%d)\n",
+ tm0->tm_year + 1900, tm0->tm_mon + 1,
+ tm0->tm_mday,
+ tm0->tm_hour, tm0->tm_min,
+ tm0->tm_sec, tm1->tm_year + 1900,
+ tm1->tm_mon + 1, tm1->tm_mday,
+ tm1->tm_hour, tm1->tm_min,
+ tm1->tm_sec);
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+static int fh_rtc_gettime_nosync(struct device *dev, struct rtc_time *rtc_tm)
+{
+ unsigned int temp;
+
+ temp = fh_rtc_get_hw_sec_data(TIME_FUNC);
+ rtc_time_to_tm(temp, rtc_tm);
+ RTC_PRINT_DBG("rtc read date:0x%x\n", temp);
+
+ return 0;
+}
+
+static int fh_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+ RTC_PRINT_DBG("rtc write %d-%d-%d %d:%d:%d\n", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
+ tm->tm_min, tm->tm_sec);
+
+ fh_rtc_set_hw_sec_data(tm, TIME_FUNC);
+
+ return 0;
+}
+
+static int fh_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rtc_time *rtc_tm = &alrm->time;
+
+ rtc_time_to_tm(fh_rtc_get_hw_sec_data(ALARM_FUNC), rtc_tm);
+
+ return 0;
+}
+
+static int fh_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rtc_time *rtc_tm = &alrm->time;
+ int status;
+
+ status = fh_rtc_set_hw_sec_data(rtc_tm, ALARM_FUNC);
+ if (status)
+ return status;
+ if (alrm->enabled)
+ fh_rtc_alarm_enable_interrupt(fh_rtc->v_addr);
+ else
+ fh_rtc_alarm_disable_interrupt(fh_rtc->v_addr,
+ FH_RTC_ISR_ALARM_POS);
+ return 0;
+}
+
+#ifdef DRIVER_TEST
+static int dump_interrput_status(unsigned int base_addr)
+{
+ int status;
+
+ status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+ pr_info("core int status : %x\n", status);
+
+ status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN);
+ pr_info("core int en : %x\n", status);
+ status = readl(fh_rtc->v_addr+FH_RTC_INT_STATUS);
+ pr_info("wrapper int status : 0x%x\n", status);
+ status = readl(fh_rtc->v_addr+FH_RTC_INT_EN);
+ pr_info("wrapper int en : 0x%x\n", status);
+ return 0;
+}
+#endif
+static int fh_rtc_irq_enable(struct device *dev, unsigned int enabled)
+{
+
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(pdev);
+ int status;
+
+ if (enabled) {
+ status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ status & (~FH_RTC_ISR_ALARM_POS));
+
+ status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN);
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN,
+ (status | FH_RTC_CORE_INT_EN_ALM_INT));
+
+ status = readl((void * __iomem)fh_rtc->v_addr+
+ FH_RTC_INT_STATUS);
+ writel(status&
+ (~FH_RTC_INT_STATUS_CORE),
+ (void * __iomem)fh_rtc->v_addr+
+ FH_RTC_INT_STATUS);
+
+ status = readl((void * __iomem)fh_rtc->v_addr +
+ FH_RTC_INT_EN);
+ writel(status &
+ (~FH_RTC_INT_CORE_INT_ERR_MASK),
+ (void * __iomem)fh_rtc->v_addr +
+ FH_RTC_INT_EN);
+
+ } else
+ fh_rtc_alarm_disable_interrupt(fh_rtc->v_addr,
+ FH_RTC_ISR_ALARM_POS);
+
+ return 0;
+}
+
+static void fh_rtc_clear_interrupt_status(unsigned int base_addr,
+ unsigned int value)
+{
+ unsigned int int_en, int_status;
+
+ int_en = readl((void * __iomem)base_addr+FH_RTC_INT_EN);
+ int_en &= 0x7f;
+ writel((((value)
+ & 0x7f)<<16)|int_en|
+ FH_RTC_INT_CORE_IDLE_ERR_MASK|
+ FH_RTC_INT_CORE_INT_ERR_MASK,
+ (void * __iomem)base_addr+FH_RTC_INT_EN);
+ int_status = value & 0x10a0;
+ writel(int_status, (void * __iomem)base_addr+
+ FH_RTC_INT_STATUS);
+}
+static struct work_struct rtc_int_wq;
+
+static void rtc_core_int_handler(struct work_struct *work)
+{
+ unsigned long events = 0;
+ int rtc_int_status, rtc_int_en;
+ unsigned int wr_int_status;
+ unsigned int wr_int_status_clr;
+ int rtc_core_status;
+ struct rtc_device *rtc = fh_rtc->rtc;
+
+ /* get core interrupt status */
+ rtc_int_en = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN);
+ wr_int_status_clr = readl((void * __iomem)fh_rtc->v_addr +
+ FH_RTC_INT_STATUS);
+ rtc_int_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+
+ /* get core interrupt failed */
+ if (rtc_int_en < 0) {
+ pr_err("can't get core int en\n");
+ return;
+ }
+ if (rtc_int_status < 0) {
+ pr_err("can't get core int status\n");
+ return;
+ }
+ /* do interrupt */
+ if (rtc_int_en & rtc_int_status & FH_RTC_ISR_ALARM_POS) {
+ pr_info("ALARM INT\n");
+ /* clear core alarm interrupt status */
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status &
+ (~FH_RTC_ISR_ALARM_POS));
+ /* eanble interrupt */
+ wr_int_status = readl((void * __iomem)fh_rtc->v_addr+
+ FH_RTC_INT_EN);
+ writel(wr_int_status&
+ (FH_RTC_INT_CORE_INT_ALL_COV),
+ (void * __iomem)fh_rtc->v_addr+FH_RTC_INT_EN);
+ /* updata to RTC CORE alarm work */
+ events |= RTC_IRQF | RTC_AF;
+ rtc_update_irq(rtc, 1, events);
+
+ } else if (rtc_int_en & rtc_int_status &
+ FH_RTC_ISR_SEC_POS) {
+
+ pr_info("FH_RTC_ISR_SEC_POS\n");
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status & (~FH_RTC_ISR_SEC_POS));
+ wr_int_status = readl((void * __iomem)fh_rtc->v_addr+
+ FH_RTC_INT_EN);
+
+ writel(wr_int_status&
+ (FH_RTC_INT_CORE_INT_STATUS_COV),
+ (void * __iomem)fh_rtc->v_addr + FH_RTC_INT_EN);
+
+ events |= RTC_IRQF | RTC_UF;
+ rtc_update_irq(rtc, 1, events);
+
+ } else if (rtc_int_en & rtc_int_status &
+ FH_RTC_ISR_MIN_POS) {
+
+ pr_info("FH_RTC_ISR_MIN_POS\n");
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status & (~FH_RTC_ISR_MIN_POS));
+ wr_int_status = readl((void * __iomem)fh_rtc->regs+
+ FH_RTC_INT_EN);
+
+ writel(wr_int_status&
+ (FH_RTC_INT_CORE_INT_ERR_MASK_COV),
+ (void * __iomem)fh_rtc->v_addr + FH_RTC_INT_EN);
+
+ writel(wr_int_status_clr&
+ (FH_RTC_INT_CORE_INT_STATUS_COV),
+ (void * __iomem)fh_rtc->v_addr + FH_RTC_INT_STATUS);
+
+ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_HOUR_POS) {
+ pr_info("FH_RTC_ISR_HOUR_POS\n");
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status & (~FH_RTC_ISR_HOUR_POS));
+ wr_int_status = readl((void * __iomem)fh_rtc->v_addr+
+ FH_RTC_INT_EN);
+
+ writel(wr_int_status&
+ (FH_RTC_INT_CORE_INT_ERR_MASK_COV),
+ (void * __iomem)fh_rtc->v_addr + FH_RTC_INT_EN);
+
+ writel(wr_int_status_clr&
+ (FH_RTC_INT_CORE_INT_STATUS_COV),
+ (void * __iomem)fh_rtc->v_addr + FH_RTC_INT_STATUS);
+ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_DAY_POS) {
+ pr_info("FH_RTC_ISR_DAY_POS\n");
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status & (~FH_RTC_ISR_DAY_POS));
+ wr_int_status = readl(fh_rtc->regs+
+ FH_RTC_INT_EN);
+
+ writel(wr_int_status&
+ (FH_RTC_INT_CORE_INT_ERR_MASK_COV),
+ (void * __iomem)fh_rtc->regs + FH_RTC_INT_EN);
+
+ writel(wr_int_status_clr&
+ (FH_RTC_INT_CORE_INT_STATUS_COV),
+ (void * __iomem)fh_rtc->regs + FH_RTC_INT_STATUS);
+ } else if (rtc_int_en & rtc_int_status &
+ FH_RTC_ISR_POWERFAIL_POS) {
+ pr_info("FH_RTC_ISR_POWERFAIL_POS\n");
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status &
+ (~FH_RTC_ISR_POWERFAIL_POS));
+
+ wr_int_status = readl((void * __iomem)fh_rtc->regs +
+ FH_RTC_INT_EN);
+
+ writel(wr_int_status_clr&
+ (FH_RTC_INT_CORE_INT_STATUS_COV),
+ (void * __iomem)fh_rtc->v_addr + FH_RTC_INT_STATUS);
+
+ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_RX_CRC_ERR_INT) {
+ pr_info("FH_RTC_ISR_RX_CRC_ERR_INT\n");
+ } else if (rtc_int_en & rtc_int_status & FH_RTC_ISR_RX_COM_ERR_INT) {
+ pr_info("FH_RTC_ISR_RX_COM_ERR_INT\n");
+ } else if (rtc_int_en & rtc_int_status & FH_RTC_LEN_ERR_INT) {
+ pr_info("FH_RTC_LEN_ERR_INT\n");
+ } else {
+ pr_info("unused isr\n");
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS, rtc_int_en & (~rtc_int_status));
+ }
+
+
+}
+
+static irqreturn_t fh_rtc_irq(int irq, void *dev_id)
+{
+ struct fh_rtc_controller *fh_rtc = (struct fh_rtc_controller *) dev_id;
+ unsigned int isr_status;
+
+ isr_status = readl((void * __iomem)fh_rtc->v_addr+FH_RTC_INT_STATUS);
+ fh_rtc_clear_interrupt_status(fh_rtc->v_addr, isr_status);
+
+ if (isr_status & FH_RTC_INT_STATUS_CORE) {
+ schedule_work(&rtc_int_wq);
+ } else if (isr_status & FH_RTC_INT_STATUS_RX_CRC_ERR)
+ pr_info("FH_RTC_INT_STATUS_RX_CRC_ERR\n");
+ else if (isr_status & FH_RTC_INT_STATUS_RX_COM_ERR) {
+ pr_info("FH_RTC_INT_STATUS_RX_COM_ERR\n");
+ } else if (isr_status & FH_RTC_INT_STATUS_RX_LEN_ERR) {
+ pr_info("FH_RTC_INT_STATUS_RX_LEN_ERR\n");
+ } else if (isr_status & FH_RTC_INT_STATUS_CNT_THL) {
+ pr_info("FH_RTC_INT_STATUS_CNT_THL\n");
+ } else if (isr_status & FH_RTC_INT_STATUS_CNT_THH) {
+ pr_info("FH_RTC_INT_STATUS_CNT_THH\n");
+ } else if (isr_status & FH_RTC_INT_STATUS_CORE_IDLE) {
+ pr_info("FH_RTC_INT_STATUS_CORE_IDLE\n");
+ } else if (isr_status & FH_RTC_INT_STATUS_WRAPPER_BUSY) {
+ pr_info("FH_RTC_INT_STATUS_WRAPPER_BUSY\n");
+ } else if (isr_status & FH_RTC_INT_STATUS_CORE_BUSY) {
+ pr_info("FH_RTC_INT_STATUS_CORE_BUSY\n");
+ } else {
+ pr_info("rtc unknown isr...\n");
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+
+}
+
+static const struct rtc_class_ops fh_rtcops = {
+ .open = fh_rtc_open,
+ .release = fh_rtc_release,
+ .read_time = fh_rtc_gettime_nosync,
+ .set_time = fh_rtc_settime,
+ .read_alarm = fh_rtc_getalarm,
+ .set_alarm = fh_rtc_setalarm,
+ .alarm_irq_enable = fh_rtc_irq_enable,
+};
+
+/*get the read of SADC and adjust RTC clock*/
+static struct miscdevice fh_rtc_misc;
+
+
+static struct of_device_id const fh_rtc_of_match[] = {
+ { .compatible = "fh,fh_rtc" },
+ {}
+};
+#ifdef CONFIG_EMULATION
+static int fh_rtc_probe(struct platform_device *pdev)
+{
+ return 0;
+}
+#else
+static int fh_rtc_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ struct rtc_device *rtc;
+ int rtc_core_status;
+ struct fh_rtc_plat_data *plat_data;
+#ifdef CONFIG_USE_OF
+ const struct of_device_id *match;
+ unsigned int paddr;
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *res;
+#endif
+
+ fh_rtc = kzalloc(sizeof(struct fh_rtc_controller), GFP_KERNEL);
+ if (!fh_rtc)
+ return -ENOMEM;
+ memset(fh_rtc, 0, sizeof(struct fh_rtc_controller));
+
+#ifdef CONFIG_USE_OF
+ match = of_match_device(fh_rtc_of_match, &pdev->dev);
+ if (!match) {
+ pr_err("failed to find rtc controller\n");
+ return -ENODEV;
+ }
+ plat_data = devm_kzalloc(&pdev->dev, sizeof(*plat_data), GFP_KERNEL);
+ if (plat_data == NULL)
+ return -ENOMEM;
+
+ fh_rtc->regs = of_iomap(np, 0);
+ if (fh_rtc->regs == NULL) {
+ err = -ENXIO;
+ return err;
+ }
+
+ err = of_property_read_u32(np, "lut_cof", &plat_data->lut_cof);
+ err |= of_property_read_u32(np, "lut_offset", &plat_data->lut_offset);
+ err |= of_property_read_u32(np, "tsensor_cp_default_out",
+ &plat_data->tsensor_cp_default_out);
+
+ if (err) {
+ dev_err(&pdev->dev, "need lut/tsensor params\n");
+ return -EINVAL;
+ }
+
+ if (of_find_property(np, "clocks", NULL))
+ fh_rtc->clk = of_clk_get(np, 0);
+
+ fh_rtc->irq = irq_of_parse_and_map(np, 0);
+ if (fh_rtc->irq < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ goto err_nores;
+ }
+ if (of_property_read_u32(np, "reg", &paddr))
+ //goto err_nores;
+ dev_err(&pdev->dev, "get rtc reg failed\n");
+ fh_rtc->paddr = paddr;
+#else
+ plat_data = (struct fh_rtc_plat_data *)dev_get_platdata(&pdev->dev);
+
+ if (plat_data->clk_name)
+ fh_rtc->clk = clk_get(NULL, plat_data->clk_name);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ fh_rtc->regs = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ fh_rtc->irq = irq_create_mapping(NULL, platform_get_irq(pdev, 0));
+ fh_rtc->paddr = res->start;
+#endif
+ fh_rtc->plat_data = plat_data;
+
+ if (fh_rtc->clk) {
+ if (IS_ERR(fh_rtc->clk)) {
+ err = PTR_ERR(fh_rtc->clk);
+ dev_err(&pdev->dev, "no clk resource\n");
+ goto err_nores;
+ } else
+ clk_prepare_enable(fh_rtc->clk);
+ }
+
+ err = request_irq(fh_rtc->irq,
+ fh_rtc_irq, IRQF_NO_THREAD, "fh_rtc", fh_rtc);
+ if (err) {
+ dev_err(&pdev->dev, "failure requesting irq %i\n", fh_rtc->irq);
+ goto err_nores;
+ }
+ fh_rtc->v_addr = (unsigned int)fh_rtc->regs;
+
+ writel(
+ FH_RTC_INT_CORE_INT_ERR_EN|
+ FH_RTC_INT_CORE_IDLE_ERR_EN |
+ FH_RTC_INT_CORE_INT_ERR_MASK |
+ FH_RTC_INT_CORE_IDLE_ERR_MASK,
+ (fh_rtc->regs+FH_RTC_INT_EN)
+ );
+ writel(
+ FH_RTC_INT_STATUS_CORE |
+ FH_RTC_INT_STATUS_CORE_IDLE,
+ fh_rtc->regs+FH_RTC_INT_STATUS);
+
+ writel(0x20, fh_rtc->regs+FH_RTC_INT_STATUS);
+ mdelay(1);
+ rtc_core_status = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS);
+ if (rtc_core_status & FH_RTC_ISR_POWERFAIL_POS) {
+ RTC_PRINT_DBG("rtc powerfailed !\n");
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status &
+ (~FH_RTC_ISR_POWERFAIL_POS));
+ }
+ /* clear all core's irq status an enable */
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_EN,
+ rtc_core_status &
+ (~FH_RTC_INT_CORE_INT_ALL_COV));
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_INT_STATUS,
+ rtc_core_status &
+ (~FH_RTC_INT_CORE_INT_ALL_COV));
+ fh_rtc_get_temp(fh_rtc->v_addr);
+
+ platform_set_drvdata(pdev, fh_rtc);
+ rtc = devm_rtc_device_register(&pdev->dev, "fh_rtc", &fh_rtcops,
+ THIS_MODULE);
+ INIT_WORK(&rtc_int_wq, rtc_core_int_handler);
+
+ if (IS_ERR(rtc)) {
+ dev_err(&pdev->dev, "cannot attach rtc\n");
+ err = PTR_ERR(rtc);
+ goto err_nores;
+ }
+ fh_rtc->rtc = rtc;
+
+ err = misc_register(&fh_rtc_misc);
+ if (err < 0)
+ dev_dbg(&pdev->dev, "register rtc misc device error\n");
+
+#ifdef USE_TSENSOR
+ rtc_adjust();
+#endif
+
+ return 0;
+
+err_nores:
+ kfree(fh_rtc);
+ return err;
+}
+#endif
+
+static int fh_rtc_remove(struct platform_device *dev)
+{
+ struct fh_rtc_controller *fh_rtc = platform_get_drvdata(dev);
+
+ free_irq(fh_rtc->irq, fh_rtc);
+ rtc_device_unregister(fh_rtc->rtc);
+ iounmap(fh_rtc->regs);
+ platform_set_drvdata(dev, NULL);
+ kfree(fh_rtc);
+
+ return 0;
+}
+
+static int fh_rtc_misc_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int fh_rtc_misc_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+long fh_rtc_misc_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int current_tsensor_data, current_offset, current_idx;
+ int status;
+ int count;
+ int lut[12] = { 0 };
+ int reg[2] = {0};
+
+ switch (cmd) {
+ case GET_TSENSOR_DATA:
+ current_tsensor_data = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_TEMP_INFO);
+ status = copy_to_user((int __user *)(arg),
+ &current_tsensor_data, 4);
+ if (status < 0)
+ pr_info("copy to user failed\n");
+ break;
+ case GET_CURRENT_OFFSET_DATA:
+ current_offset = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_OFFSET);
+ current_offset = current_offset&(0xff<<16);
+ current_offset = current_offset>>16;
+ status = copy_to_user((int __user *)(arg),
+ &current_offset, 4);
+ if (status < 0)
+ pr_info("copy to user failed\n");
+ break;
+ case GET_CURRENT_OFFSET_IDX:
+ current_offset = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_OFFSET);
+ current_idx = current_offset&(0x3f<<10);
+ current_idx = current_idx>>10;
+ status = copy_to_user((int __user *)(arg),
+ &current_idx,
+ 4);
+ if (status < 0)
+ pr_info("copy to user failed\n");
+ break;
+ case RTC_GET_LUT:
+ for (count = 0; count < 12; count++)
+ lut[count] = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_OFFSET_LUT +
+ (count<<4));
+ status = copy_to_user((int __user *)(arg), &lut[0],
+ count*4);
+ if (status < 0)
+ pr_info("copy to user failed\n");
+ break;
+ case RTC_SET_LUT:
+ status = copy_from_user(&lut[0], (int __user *)(arg),
+ 48);
+ if (status < 0)
+ pr_info("copy from user failed\n");
+ for (count = 0; count < 12; count++)
+ fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_OFFSET_LUT +
+ (count<<4),
+ lut[count]);
+ break;
+ case GET_REG_VALUE:
+ for (count = 0; count < 9; count++)
+ lut[count] = fh_rtc_get_core(fh_rtc->v_addr,
+ (count&0xf)<<4);
+
+ status = copy_to_user((int __user *)(arg), &lut[0],
+ count*4);
+ if (status < 0)
+ pr_info("copy to user failed\n");
+ break;
+ case SET_REG_VALUE:
+ status = copy_from_user(&reg[0], (int __user *)(arg),
+ 8);
+ if (status < 0)
+ pr_info("copy from user failed\n");
+
+ fh_rtc_set_core(fh_rtc->v_addr,
+ reg[0], reg[1]);
+ pr_info("set reg addr :%x, value: %x\n",
+ reg[0], reg[1]);
+ break;
+ case GET_TEMP_VALUE:
+ status = fh_rtc_get_tsensor_data(&lut[0], NULL);
+ if (status) {
+ pr_err("GET_TEMP_VALUE error %d\n", status);
+ return -EIO;
+ }
+ pr_info("temp value is %x\n", lut[0]);
+ status = copy_to_user((int __user *)(arg),
+ &lut[0], 4);
+ if (status < 0)
+ pr_info("copy to user failed\n");
+ break;
+ default:
+ pr_info("val is invalied\n");
+ break;
+ }
+ return 0;
+
+}
+static const struct file_operations fh_rtc_misc_fops = {
+ .owner = THIS_MODULE,
+ .open = fh_rtc_misc_open,
+ .release = fh_rtc_misc_release,
+ .unlocked_ioctl = fh_rtc_misc_ioctl,
+};
+
+static struct miscdevice fh_rtc_misc = {
+ .minor = RTC_MINOR,
+ .name = FH_RTC_MISC_DEVICE_NAME,
+ /*.nodename = FH_EFUSE_MISC_DEVICE_NODE_NAME,*/
+ .fops = &fh_rtc_misc_fops,
+};
+
+
+static struct platform_driver fh_rtc_driver = {
+ .driver = {
+ .name = "fh_rtc",
+ .owner = THIS_MODULE,
+ .of_match_table = fh_rtc_of_match,
+ },
+ .probe = fh_rtc_probe,
+ .remove = fh_rtc_remove,
+};
+static int __init fh_rtc_init(void)
+{
+ return platform_driver_register(&fh_rtc_driver);
+}
+
+static void __exit fh_rtc_exit(void)
+{
+ platform_driver_unregister(&fh_rtc_driver);
+}
+
+#ifdef USE_TSENSOR
+
+static int fh_rtc_temp_cfg_coef_offset(unsigned int coef, unsigned int offset)
+{
+ unsigned int temp_cfg;
+ int status;
+
+ if (coef > 0xff) {
+ pr_err("coef invalid\n");
+ return -1;
+ }
+ if (offset > 0xffff) {
+ pr_err("offset invalid\n");
+ return -1;
+ }
+ temp_cfg = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_TEMP_CFG);
+ temp_cfg &= 0xffff0000;
+ temp_cfg |= coef;
+ temp_cfg |= (offset<<8);
+
+ status = fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_TEMP_CFG,
+ temp_cfg);
+ return status;
+}
+
+static int fh_rtc_temp_cfg_thl_thh(unsigned int thl, unsigned int thh)
+{
+ unsigned int temp_cfg;
+ int status;
+
+ if (thl > 0x3f) {
+ pr_err("thl invalid\n");
+ return -1;
+ }
+ if (thh > 0x3f) {
+ pr_err("thh invalid\n");
+ return -1;
+ }
+
+ temp_cfg = fh_rtc_get_core(fh_rtc->v_addr,
+ FH_RTC_CMD_TEMP_CFG);
+ temp_cfg &= 0xf000ffff;
+ temp_cfg |= (thl<<16);
+ temp_cfg |= (thh<<22);
+
+ status = fh_rtc_set_core(fh_rtc->v_addr,
+ FH_RTC_CMD_TEMP_CFG,
+ temp_cfg);
+
+ return status;
+}
+
+#endif
+
+#ifdef CONFIG_DEFERRED_INIICALLS_RTC
+deferred_module_init(fh_rtc_init);
+#else
+module_init(fh_rtc_init);
+#endif
+module_exit(fh_rtc_exit);
+
+
+MODULE_DESCRIPTION("FH SOC RTC Driver");
+MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:fh-rtc");
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 12886f96..f40c8213 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -47,17 +47,16 @@ static void smp_task_timedout(unsigned long _task)
unsigned long flags;
spin_lock_irqsave(&task->task_state_lock, flags);
- if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
+ if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+ complete(&task->slow_task->completion);
+ }
spin_unlock_irqrestore(&task->task_state_lock, flags);
-
- complete(&task->slow_task->completion);
}
static void smp_task_done(struct sas_task *task)
{
- if (!del_timer(&task->slow_task->timer))
- return;
+ del_timer(&task->slow_task->timer);
complete(&task->slow_task->completion);
}
@@ -121,8 +120,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
}
if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == SAS_DATA_UNDERRUN) {
- /* no error, but return the number of bytes of
- * underrun */
+ /* no error, but return the number of bytes of underrun */
res = task->task_status.residual;
break;
}
@@ -556,7 +554,7 @@ static int sas_ex_manuf_info(struct domain_device *dev)
mi_req[1] = SMP_REPORT_MANUF_INFO;
- res = smp_execute_task(dev, mi_req, MI_REQ_SIZE, mi_resp,MI_RESP_SIZE);
+ res = smp_execute_task(dev, mi_req, MI_REQ_SIZE, mi_resp, MI_RESP_SIZE);
if (res) {
SAS_DPRINTK("MI: ex %016llx failed:0x%x\n",
SAS_ADDR(dev->sas_addr), res);
@@ -597,7 +595,7 @@ int sas_smp_phy_control(struct domain_device *dev, int phy_id,
pc_req[1] = SMP_PHY_CONTROL;
pc_req[9] = phy_id;
- pc_req[10]= phy_func;
+ pc_req[10] = phy_func;
if (rates) {
pc_req[32] = rates->minimum_linkrate << 4;
pc_req[33] = rates->maximum_linkrate << 4;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b7995474..7c49fe5c 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -218,6 +218,41 @@ config SPI_DESIGNWARE
help
general driver for SPI controller core from DesignWare
+config SPI_FH
+ tristate "fh spi driver for DW SPI core"
+ help
+ general driver for SPI controller core from DesignWare
+
+config SPI_FH_SLAVE
+ tristate "fh spi slave driver for DW SPI core"
+
+menu "spi multi wire support"
+depends on SPI_FH
+config SPI_USE_MULTI_WIRE
+ bool "spi0 will support 2 or 4 wire read"
+ help
+ if you set 4 wire support. 2 extra pin should switch to spi func
+ default n
+
+config SPI_SWAP_MAX_DATA_WIDTH
+ depends on SPI_USE_MULTI_WIRE
+ int "SPI_SWAP_MAX_DATA_WIDTH"
+ default 16
+endmenu
+
+config SPI_USE_DMA
+ tristate "spi xfer with external dma"
+ depends on SPI_FH && (FH_DMAC || FH_AXI_DMAC)
+ help
+ if you set; spi will use external DMA to help data xfer
+ default n
+
+config SPI_TINY_MEM
+ bool "spi tiny mem reduce code"
+ help
+ rm attribute code and dummy dma code
+ default n
+
config SPI_DW_PCI
tristate "PCI interface driver for DW SPI core"
depends on SPI_DESIGNWARE && PCI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index aa939d95..b0542448 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -102,3 +102,8 @@ obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
obj-$(CONFIG_SPI_XLP) += spi-xlp.o
obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o
obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o
+obj-$(CONFIG_SPI_FH) += spi_fh.o
+spi_fh-y += fh_spi.o
+spi_fh-$(CONFIG_SPI_USE_MULTI_WIRE) += fh_spi_multi_wire.o
+spi_fh-$(CONFIG_SPI_USE_DMA) += fh_spi_dma.o
+spi_fh-$(CONFIG_SPI_FH_SLAVE) += fh_spi_slave.o
\ No newline at end of file
diff --git a/drivers/spi/fh_spi.c b/drivers/spi/fh_spi.c
new file mode 100644
index 00000000..cad35623
--- /dev/null
+++ b/drivers/spi/fh_spi.c
@@ -0,0 +1,1104 @@
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include "fh_spi_common.h"
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type
+ * that only be used in this file here
+ ***************************************************************************/
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static u32 Spi_DisableIrq(struct fh_spi *dw, u32 irq);
+static u32 Spi_SetPolarity(struct fh_spi *dw, spi_polarity_e polarity);
+static u32 Spi_SetPhase(struct fh_spi *dw, spi_phase_e phase);
+static u32 Spi_SetFrameFormat(struct fh_spi *dw, spi_format_e format);
+static u32 Spi_SetTransferMode(struct fh_spi *dw, spi_transfer_mode_e mode);
+static u32 Spi_SetBaudrate(struct fh_spi *dw, u32 baudrate);
+static u32 Spi_ReadTxfifolevel(struct fh_spi *dw);
+static u32 Spi_ReadRxfifolevel(struct fh_spi *dw);
+static u32 Spi_ReadRxlevlel(struct fh_spi *dw);
+static u32 Spi_EnableSlaveen(struct fh_spi *dw, spi_slave_e port);
+static u32 Spi_DisableSlaveen(struct fh_spi *dw, spi_slave_e port);
+static u32 Spi_ReadData(struct fh_spi *dw);
+static u32 Spi_SetRxdelay(struct fh_spi *dw, u32 data);
+static inline u32 tx_max_tx_only(struct fh_spi_controller *fh_spi);
+static inline u32 tx_max(struct fh_spi_controller *fh_spi);
+static inline u32 rx_max(struct fh_spi_controller *fh_spi);
+static void fh_spi_check_rxfifo_depth(struct fh_spi_controller *fh_spi);
+static void spi_wait_tx_only_done(struct fh_spi_controller *fh_spi);
+static void fh_spi_plat_info_get(struct fh_spi_platform_data *p_info,
+struct platform_device *pdev);
+
+static int poll_pump_tx_only_data(struct fh_spi_controller *fh_spi);
+static int poll_rx_only_with_regwidth(struct fh_spi_controller *fh_spi,
+u8 *rxbuf, u32 size, u32 reg_width);
+
+static int poll_pump_rx_only_data(struct fh_spi_controller *fh_spi);
+static int poll_pump_tx_rx_data(struct fh_spi_controller *fh_spi);
+static void spi_ctl_fix_pump_data_mode(struct fh_spi_controller *fh_spi);
+static int poll_pump_data(struct fh_spi_controller *fh_spi);
+static irqreturn_t fh_spi_irq(int irq, void *dev_id);
+static int fh_spi_init_hw(struct fh_spi_controller *fh_spi,
+struct fh_spi_platform_data *board_info,struct spi_master *p_master);
+
+static int fh_spi_handle_message(struct fh_spi_controller *fh_spi,
+struct spi_message *m);
+
+static int fh_spi_transfer(struct fh_spi_controller *spi,
+struct spi_message *m);
+
+static int spi_transfer_one_message(struct spi_master *master,
+struct spi_message *msg);
+
+static int fh_spi_setup(struct spi_device *spi);
+static void fh_spi_cleanup(struct spi_device *spi);
+static int fh_spi_setup_transfer(struct spi_device *spi,
+struct spi_transfer *t);
+
+static int fh_spi_probe(struct platform_device *dev);
+static int fh_spi_remove(struct platform_device *dev);
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+
+
+u32 Spi_Enable(struct fh_spi *dw, spi_enable_e enable)
+{
+ dw_writel(dw, ssienr, enable);
+ return CONFIG_OK;
+}
+
+static u32 Spi_DisableIrq(struct fh_spi *dw, u32 irq)
+{
+ u32 data = 0;
+
+ data = dw_readl(dw, imr);
+ data &= ~irq;
+ dw_writel(dw, imr, data);
+ return CONFIG_OK;
+}
+
+u32 Spi_ContinueReadNum(struct fh_spi *dw, u32 num)
+{
+ dw_writel(dw, ctrl1, (num-1));
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetPolarity(struct fh_spi *dw, spi_polarity_e polarity)
+{
+ u32 data;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_POLARITY_RANGE;
+ data |= polarity;
+ dw_writel(dw, ctrl0, data);
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetPhase(struct fh_spi *dw, spi_phase_e phase)
+{
+ u32 data;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_PHASE_RANGE;
+ data |= phase;
+ dw_writel(dw, ctrl0, data);
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetFrameFormat(struct fh_spi *dw, spi_format_e format)
+{
+ u32 data = 0;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_FRAME_FORMAT_RANGE;
+ data |= format;
+ dw_writel(dw, ctrl0, data);
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetTransferMode(struct fh_spi *dw, spi_transfer_mode_e mode)
+{
+ u32 data = 0;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_TRANSFER_MODE_RANGE;
+ data |= mode;
+ dw_writel(dw, ctrl0, data);
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetBaudrate(struct fh_spi *dw, u32 baudrate)
+{
+ dw_writel(dw, baudr, baudrate);
+ return CONFIG_OK;
+}
+
+static u32 Spi_ReadTxfifolevel(struct fh_spi *dw)
+{
+ return dw_readl(dw, txflr);
+}
+
+static u32 Spi_ReadRxfifolevel(struct fh_spi *dw)
+{
+ return (u32) dw_readl(dw, rxflr);
+}
+
+static u32 Spi_ReadRxlevlel(struct fh_spi *dw)
+{
+ return dw_readl(dw, rxfltr);
+}
+
+u32 Spi_SetRxlevlel(struct fh_spi *dw, u32 level)
+{
+ dw_writel(dw, rxfltr, level);
+ return CONFIG_OK;
+}
+
+u32 Spi_ReadStatus(struct fh_spi *dw)
+{
+ return (u32) dw_readl(dw, sr);
+}
+
+static u32 Spi_EnableSlaveen(struct fh_spi *dw, spi_slave_e port)
+{
+ u32 data = 0;
+
+ gpio_direction_output(dw->active_cs_pin, 0);
+ data = dw_readl(dw, ser);
+ data |= port;
+ dw_writel(dw, ser, data);
+ return CONFIG_OK;
+}
+
+static u32 Spi_DisableSlaveen(struct fh_spi *dw, spi_slave_e port)
+{
+ u32 data = 0;
+
+ gpio_direction_output(dw->active_cs_pin, 1);
+ data = dw_readl(dw, ser);
+ data &= ~port;
+ dw_writel(dw, ser, data);
+ return CONFIG_OK;
+}
+
+u32 Spi_WriteData(struct fh_spi *dw, u32 data)
+{
+ dw_writel(dw, dr, data);
+ return WRITE_ONLY_OK;
+}
+
+static u32 Spi_ReadData(struct fh_spi *dw)
+{
+ return dw_readl(dw, dr);
+}
+
+static u32 Spi_SetRxdelay(struct fh_spi *dw, u32 data)
+{
+ dw_writel(dw, rx_sample_dly, data);
+ return CONFIG_OK;
+}
+
+u32 Spi_RawIsrstatus(struct fh_spi *dw)
+{
+ u32 data = dw_readl(dw, risr);
+ return data;
+}
+
+static inline u32 tx_max_tx_only(struct fh_spi_controller *fh_spi)
+{
+ u32 hw_tx_level;
+
+ hw_tx_level = Spi_ReadTxfifolevel(&fh_spi->dwc);
+ hw_tx_level = fh_spi->dwc.fifo_len - hw_tx_level;
+
+ return min(hw_tx_level, fh_spi->dwc.tx_len);
+}
+
+static inline u32 tx_max(struct fh_spi_controller *fh_spi)
+{
+
+ u32 hw_tx_level, hw_rx_level;
+ u32 temp_tx_lev;
+
+ temp_tx_lev = Spi_ReadTxfifolevel(&fh_spi->dwc);
+ hw_rx_level = temp_tx_lev + Spi_ReadRxfifolevel(&fh_spi->dwc);
+ if (hw_rx_level >= fh_spi->dwc.fifo_len)
+ return 0;
+ /* add shift data... maybe should add apb bus delay */
+ hw_rx_level++;
+
+ hw_tx_level = temp_tx_lev;
+ hw_tx_level = fh_spi->dwc.fifo_len - hw_tx_level;
+ hw_rx_level = fh_spi->dwc.fifo_len - hw_rx_level;
+ /* min(hw_tx_level, fh_spi->dwc.tx_len); */
+ return min(min(hw_tx_level, fh_spi->dwc.tx_len), hw_rx_level);
+}
+
+
+/* Return the max entries we should read out of rx fifo */
+static inline u32 rx_max(struct fh_spi_controller *fh_spi)
+{
+ u32 hw_rx_level;
+
+ hw_rx_level = Spi_ReadRxfifolevel(&fh_spi->dwc);
+ return hw_rx_level;
+}
+
+static void fh_spi_check_rxfifo_depth(struct fh_spi_controller *fh_spi)
+{
+ u32 w_i, r_i, ori;
+
+ ori = Spi_ReadRxlevlel(&fh_spi->dwc);
+ for (r_i = w_i = RX_FIFO_MIN_LEN; w_i < RX_FIFO_MAX_LEN; r_i++) {
+ Spi_SetRxlevlel(&fh_spi->dwc, ++w_i);
+ if (r_i == Spi_ReadRxlevlel(&fh_spi->dwc))
+ break;
+ }
+ Spi_SetRxlevlel(&fh_spi->dwc, ori);
+ fh_spi->dwc.fifo_len = r_i + 1;
+}
+
+
+static void spi_wait_tx_only_done(struct fh_spi_controller *fh_spi)
+{
+ u32 status;
+
+ do {
+ status = Spi_ReadStatus(&fh_spi->dwc);
+ } while ((status & 0x01) || (!(status & 0x04)));
+}
+
+
+static void fh_spi_plat_info_get(struct fh_spi_platform_data *p_info,
+struct platform_device *pdev)
+{
+
+#ifdef CONFIG_USE_OF
+ struct device_node *np = pdev->dev.of_node;
+ int temp, i;
+ char spi_cs_name[20] = { 0 };
+
+ if (!of_property_read_u32(np, "clk_in", &temp))
+ p_info->apb_clock_in = temp;
+ if (!of_property_read_u32(np, "num-cs", &temp))
+ p_info->slave_max_num = temp;
+ if (!of_property_read_u32(np, "bus_no", &temp))
+ p_info->bus_no = temp;
+ if (!of_property_read_u32(np, "multi_wire_size", &temp))
+ p_info->ctl_wire_support = temp;
+ if (!of_property_read_u32(np, "clock_source_num", &temp))
+ p_info->clock_source_num = temp;
+ if (p_info->clock_source_num)
+ of_property_read_u32_array(np, "clock_source", p_info->clock_source, p_info->clock_source_num);
+
+ p_info->clk_name = (char *)of_get_property(np, "clk_name", &temp);
+ p_info->hclk_name = (char *)of_get_property(np, "hclk_name", &temp);
+ p_info->pclk_name = (char *)of_get_property(np, "pclk_name", &temp);
+
+ /* dma para >>*/
+
+ if (strcmp("enable", of_get_property(np, "dma_enable", &temp)) == 0)
+ p_info->dma_transfer_enable = SPI_TRANSFER_USE_DMA;
+ if (!of_property_read_u32(np, "rx_hs_no", &temp))
+ p_info->rx_handshake_num = temp;
+ if (!of_property_read_u32(np, "rx_dma_channel", &temp))
+ p_info->rx_dma_channel = temp;
+ if (strcmp("enable", of_get_property(np, "dma_protctl_enable", &temp)) == 0)
+ p_info->dma_protctl_enable = SPI_DMA_PROTCTL_ENABLE;
+ if (!of_property_read_u32(np, "dma_protctl_data", &temp))
+ p_info->dma_protctl_data = temp;
+ if (strcmp("enable", of_get_property(np, "dma_master_sel_enable", &temp)) == 0)
+ p_info->dma_master_sel_enable = SPI_DMA_MASTER_SEL_ENABLE;
+ if (!of_property_read_u32(np, "dma_master_ctl_sel", &temp))
+ p_info->dma_master_ctl_sel = temp;
+ if (!of_property_read_u32(np, "dma_master_mem_sel", &temp))
+ p_info->dma_master_mem_sel = temp;
+
+ /* <<dma para */
+
+ for (i = 0; i < p_info->slave_max_num; i++) {
+ sprintf(spi_cs_name, "%s%d%s", "cs", i, "_gpio");
+ if (!of_property_read_u32(np, spi_cs_name, &temp))
+ p_info->cs_data[i].GPIO_Pin = temp;
+ else
+ BUG_ON(1);
+ }
+#else
+ /* just cpy plat data.*/
+ memcpy((void *)p_info, (void *)pdev->dev.platform_data,
+ sizeof(struct fh_spi_platform_data));
+ if(p_info->ctl_wire_support & QUAD_WIRE_SUPPORT)
+ p_info->ctl_wire_support = 4;
+ else if(p_info->ctl_wire_support & DUAL_WIRE_SUPPORT)
+ p_info->ctl_wire_support = 2;
+ else
+ p_info->ctl_wire_support = 1;
+#endif
+
+ if (p_info->slave_max_num >
+ SPI_MASTER_CONTROLLER_MAX_SLAVE) {
+ dev_err(&pdev->dev, "plat set slave gpio too much 0x%x\n", p_info->slave_max_num);
+ BUG_ON(1);
+ }
+}
+
+
+static int poll_pump_tx_only_data(struct fh_spi_controller *fh_spi)
+{
+ register u32 tx_fifo_capability;
+ u8 *txbuf;
+
+ txbuf = (u8 *) fh_spi->dwc.tx_buff;
+ /*tx_max_tx_only*/
+ while (fh_spi->dwc.tx_len) {
+ tx_fifo_capability = tx_max_tx_only(fh_spi);
+ fh_spi->dwc.tx_len -= tx_fifo_capability;
+ while (tx_fifo_capability) {
+ Spi_WriteData(&fh_spi->dwc, *txbuf++);
+ fh_spi->dwc.tx_buff++;
+ tx_fifo_capability--;
+ }
+ }
+ /*wait idle and tx fifo empty..*/
+ spi_wait_tx_only_done(fh_spi);
+ return 0;
+}
+
+
+
+u32 rx_only_fix_data_width(struct fh_spi_controller *fh_spi, u32 size)
+{
+ u32 data_width = 0;
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if(check_spi_sup_multi_wire(fh_spi))
+ {
+ if (!(((int)fh_spi->dwc.rx_buff % 4) || (size % 4)))
+ data_width = 32;
+ else if (!(((int)fh_spi->dwc.rx_buff % 2) || (size % 2)))
+ data_width = 16;
+ else
+ data_width = 8;
+ data_width = min(data_width, fh_spi->dwc.multi_para.swap_max_size);
+ }
+ else
+ data_width = 8;
+#else
+ data_width = 8;
+#endif
+
+ return data_width;
+}
+
+static int poll_rx_only_with_regwidth(struct fh_spi_controller *fh_spi,
+u8 *rxbuf, u32 size, u32 reg_width)
+{
+ register u32 rx_fifo_capability;
+ u32 otp_xfer_size;
+ u8 *rxbuf_8;
+ u16 *rxbuf_16;
+ u32 *rxbuf_32;
+
+ rxbuf_8 = (u8 *)rxbuf;
+ rxbuf_16 = (u16 *)rxbuf;
+ rxbuf_32 = (u32 *)rxbuf;
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if (reg_width > 8)
+ fh_spi->dwc.multi_para.swap_data_width(fh_spi, reg_width);
+#endif
+
+ /* refix size div reg_width */
+ size = size / (reg_width / 8);
+ /* printk("reg width is %d\n",reg_width); */
+start:
+ /* or rx fifo error.. */
+ if (size == 0) {
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if (reg_width > 8)
+ fh_spi->dwc.multi_para.swap_data_width(fh_spi, 8);
+#endif
+ return 0;
+ }
+
+ otp_xfer_size = min((u32)fh_spi->dwc.fifo_len, size);
+ size -= otp_xfer_size;
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_ContinueReadNum(&fh_spi->dwc, otp_xfer_size);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+ Spi_WriteData(&fh_spi->dwc, 0xffffffff);
+ do {
+ rx_fifo_capability = rx_max(fh_spi);
+ otp_xfer_size -= rx_fifo_capability;
+ while (rx_fifo_capability) {
+ if (reg_width == 32)
+ *rxbuf_32++ = (u32)Spi_ReadData(&fh_spi->dwc);
+ else if (reg_width == 16)
+ *rxbuf_16++ = (u16)Spi_ReadData(&fh_spi->dwc);
+ else
+ *rxbuf_8++ = (u8)Spi_ReadData(&fh_spi->dwc);
+ rx_fifo_capability--;
+ }
+ }
+ while (otp_xfer_size);
+ goto start;
+}
+
+static int poll_pump_rx_only_data(struct fh_spi_controller *fh_spi)
+{
+ u32 size;
+ int ret;
+ u32 data_width = 0;
+
+ size = fh_spi->dwc.tx_len;
+ data_width = rx_only_fix_data_width(fh_spi, size);
+ ret = poll_rx_only_with_regwidth(fh_spi,
+ fh_spi->dwc.rx_buff, size, data_width);
+
+ return ret;
+
+}
+
+static int poll_pump_tx_rx_data(struct fh_spi_controller *fh_spi)
+{
+ register u32 rx_fifo_capability, tx_fifo_capability;
+ u8 *txbuf;
+ u8 *rxbuf;
+ u16 data;
+ u32 size;
+
+ rxbuf = (u8 *)fh_spi->dwc.rx_buff;
+ txbuf = (u8 *)fh_spi->dwc.tx_buff;
+ size = fh_spi->active_transfer->len;
+
+ goto first;
+start:
+ rx_fifo_capability = rx_max(fh_spi);
+ fh_spi->dwc.rx_len += rx_fifo_capability;
+ if (rxbuf != NULL) {
+ fh_spi->dwc.rx_buff += rx_fifo_capability;
+ while (rx_fifo_capability) {
+ *rxbuf++ = Spi_ReadData(&fh_spi->dwc);
+ rx_fifo_capability--;
+ }
+
+ } else {
+ while (rx_fifo_capability) {
+ data = Spi_ReadData(&fh_spi->dwc);
+ rx_fifo_capability--;
+ }
+ }
+ if (fh_spi->dwc.rx_len == size)
+ return 0;
+first:
+ tx_fifo_capability = tx_max(fh_spi);
+ fh_spi->dwc.tx_len -= tx_fifo_capability;
+ if (txbuf != NULL) {
+ fh_spi->dwc.tx_buff += tx_fifo_capability;
+ while (tx_fifo_capability) {
+ Spi_WriteData(&fh_spi->dwc, *txbuf++);
+ tx_fifo_capability--;
+ }
+
+ } else {
+ while (tx_fifo_capability) {
+ Spi_WriteData(&fh_spi->dwc, 0xff);
+ tx_fifo_capability--;
+ }
+ }
+
+ goto start;
+}
+
+static void spi_ctl_fix_pump_data_mode(struct fh_spi_controller *fh_spi)
+{
+
+ if ((fh_spi->dwc.rx_buff == NULL) && (fh_spi->dwc.tx_buff != NULL))
+ fh_spi->dwc.transfer_mode = SPI_ONLY_TX_MODE;
+ else if ((fh_spi->dwc.rx_buff != NULL) && (fh_spi->dwc.tx_buff == NULL))
+ fh_spi->dwc.transfer_mode = SPI_ONLY_RX_MODE;
+ else
+ fh_spi->dwc.transfer_mode = SPI_TX_RX_MODE;
+}
+
+static int poll_pump_data(struct fh_spi_controller *fh_spi)
+{
+
+ if (fh_spi->dwc.transfer_mode == SPI_ONLY_TX_MODE)
+ poll_pump_tx_only_data(fh_spi);
+ else if (fh_spi->dwc.transfer_mode == SPI_ONLY_RX_MODE)
+ poll_pump_rx_only_data(fh_spi);
+ else
+ poll_pump_tx_rx_data(fh_spi);
+
+ return 0;
+}
+
+
+static irqreturn_t fh_spi_irq(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+
+static int fh_spi_init_hw(struct fh_spi_controller *fh_spi,
+struct fh_spi_platform_data *board_info,struct spi_master *p_master)
+{
+ int status, i;
+
+ fh_spi->dwc.id = board_info->bus_no;
+ fh_spi_check_rxfifo_depth(fh_spi);
+ fh_spi->dwc.num_cs = board_info->slave_max_num;
+ for (i = 0; i < fh_spi->dwc.num_cs; i++) {
+ fh_spi->dwc.cs_data[i].GPIO_Pin =
+ board_info->cs_data[i].GPIO_Pin;
+ fh_spi->dwc.cs_data[i].name = board_info->cs_data[i].name;
+ }
+ fh_spi->dwc.transfer_mode = SPI_TX_RX_MODE;
+ do {
+ status = Spi_ReadStatus(&fh_spi->dwc);
+ } while (status & 0x01);
+
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_DisableIrq(&fh_spi->dwc, SPI_IRQ_ALL);
+ Spi_SetFrameFormat(&fh_spi->dwc, SPI_MOTOROLA_MODE);
+ Spi_SetTransferMode(&fh_spi->dwc, fh_spi->dwc.transfer_mode);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+ return 0;
+}
+
+
+static int fh_spi_handle_message(struct fh_spi_controller *fh_spi,
+struct spi_message *m)
+{
+ bool first, last;
+ struct spi_transfer *t, *tmp_t;
+ int status = 0;
+ int cs_change;
+ struct spi_device *spi_dev;
+ struct spi_master *spi_master;
+ u8 pump_mode = PUMP_DATA_POLL_MODE;
+
+ cs_change = 1;
+ m->actual_length = 0;
+ fh_spi->active_message = m;
+ /*get spi slave from the message bind on it.*/
+ spi_dev = m->spi;
+ spi_master = spi_dev->master;
+ /*bind the active spi dev to the controller..*/
+ fh_spi->active_spi_dev = spi_dev;
+ list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list)
+ {
+ first = (&t->transfer_list == m->transfers.next);
+ last = (&t->transfer_list == m->transfers.prev);
+ if (first || t->speed_hz || t->bits_per_word)
+ fh_spi_setup_transfer(m->spi, t);
+
+ if (cs_change)
+ Spi_EnableSlaveen(&fh_spi->dwc, fh_spi->dwc.slave_port);
+ cs_change = t->cs_change;
+ fh_spi->active_transfer = t;
+ fh_spi->dwc.tx_len = t->len;
+ fh_spi->dwc.rx_len = 0;
+ fh_spi->dwc.tx_buff = (void *) t->tx_buf;
+ fh_spi->dwc.rx_buff = t->rx_buf;
+
+ /* here we don't need to check multi wire tobe legal...
+ the spi core 'spi_setup' will make sure the spi dev and core have right open mode.*/
+
+ spi_ctl_fix_pump_data_mode(fh_spi);
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if(check_spi_sup_multi_wire(fh_spi))
+ fh_spi->dwc.multi_para.fix_wire_mode(fh_spi);
+#endif
+
+
+#ifdef CONFIG_SPI_USE_DMA
+ if (!!fh_spi->dwc.board_info->dma_transfer_enable){
+ if (fh_spi->dwc.transfer_mode == SPI_ONLY_RX_MODE && t->len > DMA_TRANS_GATE_LEVEL){
+ if(((unsigned int)t->rx_buf % 4 == 0) && (t->len % 4 == 0)){
+ pump_mode = PUMP_DATA_DMA_MODE;
+ }
+ }
+ }
+#endif
+
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_SetTransferMode(&fh_spi->dwc, fh_spi->dwc.transfer_mode);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+ switch(pump_mode){
+#ifdef CONFIG_SPI_USE_DMA
+ case PUMP_DATA_DMA_MODE:
+ status = fh_spi->dwc.dma_para.dma_read(fh_spi);
+ break;
+#endif
+ case PUMP_DATA_POLL_MODE:
+ status = poll_pump_data(fh_spi);
+ break;
+
+ default:
+ BUG_ON(1);
+ break;
+
+ }
+
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ /*back to onewire.*/
+ if(check_spi_sup_multi_wire(fh_spi))
+ fh_spi->dwc.multi_para.change_1_wire(fh_spi->active_spi_dev->master);
+#endif
+
+ if (!cs_change && last)
+ Spi_DisableSlaveen(&fh_spi->dwc,
+ fh_spi->dwc.slave_port);
+
+ m->actual_length += t->len;
+ if (status)
+ break;
+ }
+
+ return status;
+}
+
+
+static int fh_spi_transfer(struct fh_spi_controller *spi,
+struct spi_message *m)
+{
+ struct fh_spi_controller *fh_spi = spi;
+
+ mutex_lock(&fh_spi->lock);
+ m->status = -EINPROGRESS;
+ m->status = fh_spi_handle_message(fh_spi, m);
+ mutex_unlock(&fh_spi->lock);
+ return 0;
+
+}
+
+static int spi_transfer_one_message(struct spi_master *master,
+struct spi_message *msg)
+{
+ struct fh_spi_controller *fh_spi = spi_master_get_devdata(master);
+ /*here may be i should start a queue work.*/
+ fh_spi_transfer(fh_spi,msg);
+ /* call core to set msg done */
+ spi_finalize_current_message(master);
+ return 0;
+}
+
+
+static int fh_spi_setup(struct spi_device *spi)
+{
+ /* spi_setup() does basic checks,
+ * stmp_spi_setup_transfer() does more later
+ */
+ struct fh_spi_controller *fh_spi = spi_master_get_devdata(spi->master);
+
+ fh_spi->dwc.active_cs_pin =
+ fh_spi->dwc.cs_data[spi->chip_select].GPIO_Pin;
+
+ if (spi->chip_select >= fh_spi->dwc.num_cs) {
+ dev_err(&spi->dev, "%s, unsupported chip select no=%d\n",
+ __func__, spi->chip_select);
+ return -EINVAL;
+ }
+ fh_spi->dwc.slave_port = 1 << spi->chip_select;
+
+ if (spi->bits_per_word != 8) {
+ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+ __func__, spi->bits_per_word);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*free the controller malloc data for the spi_dev*/
+static void fh_spi_cleanup(struct spi_device *spi)
+{
+
+}
+
+static u32 fh_spi_clock_adjust(u32 *div,
+struct fh_spi_controller *fh_spi, u32 speed)
+{
+ u32 rate;
+ struct clk *clk;
+
+ u32 delta = 0xFFFFFFFF;
+ u32 i = 0;
+ u32 j = 1;
+ u32 selected_rate = 0;
+ u32 selected_div = 0;
+ u32 *clock_source = fh_spi->dwc.board_info->clock_source;
+ u32 source_num = fh_spi->dwc.board_info->clock_source_num;
+
+ if (fh_spi->dwc.board_info->clock_in_use == speed)
+ return 0;
+
+ for (; i < source_num; i++) {
+ for (j = 1; j < 0xFF; j++) {
+ rate = clock_source[i] / (j * 2);
+
+ if (rate <= speed) {
+ if (delta > (speed - rate)) {
+ delta = speed - rate;
+ selected_rate = clock_source[i];
+ selected_div = j * 2;
+ }
+ }
+ }
+ }
+
+ clk = clk_get(&fh_spi->p_dev->dev, fh_spi->dwc.board_info->clk_name);
+ clk_set_rate(clk, selected_rate);
+ *div = selected_div;
+ fh_spi->dwc.board_info->clock_in_use = speed;
+
+ return 1;
+}
+
+static int fh_spi_setup_transfer(struct spi_device *spi,
+struct spi_transfer *t)
+{
+
+ u8 bits_per_word;
+ u32 hz;
+ u32 div;
+ u32 res;
+ u32 cpol,cpha;
+ struct fh_spi_controller *fh_spi = spi_master_get_devdata(spi->master);
+
+ bits_per_word = spi->bits_per_word;
+ if (t && t->bits_per_word)
+ bits_per_word = t->bits_per_word;
+
+ /*
+ * Calculate speed:
+ * - by default, use maximum speed from ssp clk
+ * - if device overrides it, use it
+ * - if transfer specifies other speed, use transfer's one
+ */
+
+ hz = fh_spi->dwc.max_freq;
+ if (spi->max_speed_hz)
+ hz = min(hz, spi->max_speed_hz);
+
+ res = fh_spi_clock_adjust(&div, fh_spi, hz);
+
+ if (bits_per_word != 8) {
+ dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
+ __func__, bits_per_word);
+ return -EINVAL;
+ }
+
+ if (spi->mode & SPI_CPOL)
+ cpol = SPI_POLARITY_HIGH;
+ else
+ cpol = SPI_POLARITY_LOW;
+
+ if (spi->mode & SPI_CPHA)
+ cpha = SPI_PHASE_TX_FIRST;
+ else
+ cpha = SPI_PHASE_RX_FIRST;
+
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_SetPolarity(&fh_spi->dwc, cpol);
+ Spi_SetPhase(&fh_spi->dwc, cpha);
+ if (res)
+ Spi_SetBaudrate(&fh_spi->dwc, div);
+ Spi_SetRxdelay(&fh_spi->dwc, spi->sample_delay);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+ fh_spi_setup(spi);
+
+ return 0;
+}
+
+static int fh_spi_probe(struct platform_device *dev)
+{
+
+ int err = 0;
+ struct spi_master *master;
+ struct fh_spi_controller *fh_spi;
+ int ret, i, j;
+ struct clk *clk;
+#ifdef CONFIG_USE_OF
+ struct device_node *np;
+ struct resource res;
+#else
+ struct resource *p_res;
+#endif
+ /*board info below*/
+ struct fh_spi_platform_data *spi_platform_info;
+
+ spi_platform_info = kzalloc(sizeof(struct fh_spi_platform_data), GFP_KERNEL);
+ if (!spi_platform_info) {
+ err = -ENOMEM;
+ dev_err(&dev->dev, "%s, master malloc failed.\n", __func__);
+ goto out0;
+ }
+
+ master = spi_alloc_master(&dev->dev, sizeof(struct fh_spi_controller));
+ if (master == NULL) {
+ err = -ENOMEM;
+ kfree(spi_platform_info);
+ dev_err(&dev->dev, "%s, master malloc failed.\n", __func__);
+ goto out0;
+ }
+
+ fh_spi_plat_info_get(spi_platform_info, dev);
+
+ fh_spi = spi_master_get_devdata(master);
+ if (!fh_spi) {
+ dev_err(&dev->dev, "%s, master dev data is null.\n", __func__);
+ err = -ENOMEM;
+ //free the spi master data
+ goto out_put_master;
+ }
+ /* controller's master dev is platform dev~~ */
+ fh_spi->master_dev = &dev->dev;
+ /* bind the platform dev */
+ fh_spi->p_dev = dev;
+
+ /* set the platform dev private data */
+ platform_set_drvdata(dev, master);
+#ifdef CONFIG_USE_OF
+ int id;
+ np = dev->dev.of_node;
+ fh_spi->dwc.regs = of_iomap(np, 0);
+ of_address_to_resource(np, 0, &res);
+ fh_spi->dwc.paddr = res.start;
+ fh_spi->dwc.irq = irq_of_parse_and_map(np, 0);
+ id = of_alias_get_id(np, "spi");
+ sprintf(fh_spi->dwc.isr_name, "spi-%d", id);
+#else
+ p_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!p_res)
+ BUG_ON(1);
+ fh_spi->dwc.regs = ioremap(p_res->start, resource_size(p_res));
+ fh_spi->dwc.paddr = p_res->start;
+ fh_spi->dwc.irq = platform_get_irq(dev, 0);
+ fh_spi->dwc.irq = irq_create_mapping(NULL, fh_spi->dwc.irq);
+ sprintf(fh_spi->dwc.isr_name, "spi-%d", dev->id);
+#endif
+
+ if (!fh_spi->dwc.irq) {
+ pr_err("%s: ERROR: getting resource failed"
+ "cannot get IORESOURCE_IRQ\n", __func__);
+ ret = -ENXIO;
+ goto out_put_master;
+ }
+ err = request_irq(fh_spi->dwc.irq, fh_spi_irq, 0, fh_spi->dwc.isr_name,
+ fh_spi);
+ if (err) {
+ dev_dbg(&dev->dev, "request_irq failed, %d\n", err);
+ goto out_set_plat_drvdata_null;
+ }
+
+ mutex_init(&fh_spi->lock);
+ master->bus_num = spi_platform_info->bus_no;
+ master->transfer_one_message = spi_transfer_one_message;
+ master->setup = fh_spi_setup;
+ master->cleanup = fh_spi_cleanup;
+
+ master->max_speed_hz = spi_platform_info->apb_clock_in / 2;
+ fh_spi->dwc.max_freq = spi_platform_info->apb_clock_in / 2;
+ master->dev.of_node = dev->dev.of_node;
+ /* support 8bit one work.. */
+ master->bits_per_word_mask = SPI_BPW_MASK(8);
+ master->dev.of_node = dev->dev.of_node;
+ master->num_chipselect = spi_platform_info->slave_max_num;
+ master->mode_bits = SPI_CPOL | SPI_CPHA;
+
+ clk = clk_get(&fh_spi->p_dev->dev, spi_platform_info->clk_name);
+ if (IS_ERR(clk)) {
+ dev_err(&fh_spi->p_dev->dev, "cannot find the spi%d clk.\n",
+ fh_spi->dwc.id);
+ err = PTR_ERR(clk);
+ goto out_free_irq;
+ }
+ clk_set_rate(clk, SPI_DEFAULT_CLK);
+ clk_prepare_enable(clk);
+
+ if (spi_platform_info->hclk_name) {
+ clk = clk_get(&fh_spi->p_dev->dev,
+ spi_platform_info->hclk_name);
+ if (IS_ERR(clk)) {
+ dev_err(&fh_spi->p_dev->dev, "cannot find the spi%d hclk.\n",
+ fh_spi->dwc.id);
+ err = PTR_ERR(clk);
+ goto out_free_irq;
+ }
+ clk_prepare_enable(clk);
+ }
+
+ if (spi_platform_info->pclk_name) {
+ clk = clk_get(&fh_spi->p_dev->dev,
+ spi_platform_info->pclk_name);
+ if (IS_ERR(clk)) {
+ dev_err(&fh_spi->p_dev->dev, "cannot find the spi%d pclk.\n",
+ fh_spi->dwc.id);
+ err = PTR_ERR(clk);
+ goto out_free_irq;
+ }
+ clk_prepare_enable(clk);
+ }
+ fh_spi->dwc.board_info = spi_platform_info;
+ ret = fh_spi_init_hw(fh_spi, spi_platform_info, master);
+
+ if (ret) {
+ err = ret;
+ goto out_free_irq;
+ }
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if(check_spi_sup_multi_wire(fh_spi))
+ spic_multi_wire_init(master);
+#endif
+
+#ifdef CONFIG_SPI_USE_DMA
+ fh_spi_dma_init(fh_spi);
+#endif
+
+ for (i = 0; i < fh_spi->dwc.num_cs; i++) {
+ ret = gpio_request(fh_spi->dwc.cs_data[i].GPIO_Pin,
+ fh_spi->dwc.cs_data[i].name);
+ if (ret) {
+ dev_err(&dev->dev,
+ "spi failed to request the gpio:%d\n",
+ fh_spi->dwc.cs_data[i].GPIO_Pin);
+
+ if (i != 0) {
+ for (j = 0; j < i; j++)
+ gpio_free(fh_spi->dwc.cs_data[j].GPIO_Pin);
+ }
+ err = ret;
+
+ goto out_clk_disable;
+ }
+
+ gpio_direction_output(fh_spi->dwc.cs_data[i].GPIO_Pin,
+ GPIOF_OUT_INIT_HIGH);
+ }
+ err = spi_register_master(master);
+ if (err) {
+ dev_dbg(&dev->dev, "cannot register spi master, %d\n", err);
+ goto out_gpio_tree;
+ }
+
+ return 0;
+
+out_gpio_tree:
+ for (i = 0; i < fh_spi->dwc.num_cs; i++)
+ gpio_free(fh_spi->dwc.cs_data[i].GPIO_Pin);
+
+out_clk_disable:
+out_free_irq:
+ free_irq(fh_spi->dwc.irq, fh_spi);
+out_set_plat_drvdata_null:
+ memset(fh_spi, 0, sizeof(struct fh_spi_controller));
+ platform_set_drvdata(dev, NULL);
+out_put_master:
+ kfree(spi_platform_info);
+ spi_master_put(master);
+out0:
+ return err;
+
+}
+
+
+static int fh_spi_remove(struct platform_device *dev)
+{
+ struct resource *r;
+ struct spi_master *master;
+ struct fh_spi_controller *fh_spi;
+ int i;
+
+ master = platform_get_drvdata(dev);
+ if (master == NULL)
+ goto out0;
+
+ fh_spi = spi_master_get_devdata(master);
+ spi_unregister_master(master);
+ /*gpio free*/
+ for (i = 0; i < fh_spi->dwc.num_cs; i++)
+ gpio_free(fh_spi->dwc.cs_data[i].GPIO_Pin);
+ /*clk disable*/
+ /*queue free*/
+#ifdef CONFIG_SPI_USE_DMA
+ if (fh_spi->dwc.board_info->dma_transfer_enable == SPI_TRANSFER_USE_DMA) {
+ if(fh_spi->dwc.dma_para.rx.chan) {
+ dma_release_channel(fh_spi->dwc.dma_para.rx.chan);
+ fh_spi->dwc.dma_para.rx.chan->private = NULL;
+ }
+ }
+#endif
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ /*io map free*/
+ iounmap(fh_spi->dwc.regs);
+ /*mem region free*/
+ release_mem_region(r->start, resource_size(r));
+ /*irq free*/
+ free_irq(fh_spi->dwc.irq, fh_spi);
+ /*clear the spi master dev data*/
+ memset(fh_spi, 0, sizeof(struct fh_spi_controller));
+ /*put master*/
+ platform_set_drvdata(dev, NULL);
+ spi_master_put(master);
+
+out0:
+ return 0;
+
+
+}
+
+static const struct of_device_id fh_spi_of_match[] = {
+ {.compatible = "fh,fh-spi",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_spi_of_match);
+
+static struct platform_driver fh_spi_driver = {
+ .driver = {
+ .name = "fh_spi",
+ .of_match_table = fh_spi_of_match,
+ },
+ .probe = fh_spi_probe,
+ .remove = fh_spi_remove,
+};
+
+#ifdef CONFIG_DEFERRED_INIICALLS_SPI
+deferred_module_platform_driver(fh_spi_driver);
+#else
+module_platform_driver(fh_spi_driver);
+#endif
+
+MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>");
+MODULE_DESCRIPTION("Fullhan SPI device driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/fh_spi_common.h b/drivers/spi/fh_spi_common.h
new file mode 100644
index 00000000..c01393a1
--- /dev/null
+++ b/drivers/spi/fh_spi_common.h
@@ -0,0 +1,386 @@
+#ifndef __FH_SPI_COMMON_H__
+#define __FH_SPI_COMMON_H__
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/irqreturn.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include <linux/crc32.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/fh_dmac.h>
+#include <mach/fh_dma_plat.h>
+#include <mach/fh_spi_plat.h>
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+#define SPI_DEFAULT_CLK (100000000)
+
+#define lift_shift_bit_num(bit_num) (1<<bit_num)
+//read spi irq, only useful if you set which is masked
+#define SPI_IRQ_TXEIS (lift_shift_bit_num(0))
+#define SPI_IRQ_TXOIS (lift_shift_bit_num(1))
+#define SPI_IRQ_RXUIS (lift_shift_bit_num(2))
+#define SPI_IRQ_RXOIS (lift_shift_bit_num(3))
+#define SPI_IRQ_RXFIS (lift_shift_bit_num(4))
+#define SPI_IRQ_MSTIS (lift_shift_bit_num(5))
+//spi status
+#define SPI_STATUS_BUSY (lift_shift_bit_num(0))
+#define SPI_STATUS_TFNF (lift_shift_bit_num(1))
+#define SPI_STATUS_TFE (lift_shift_bit_num(2))
+#define SPI_STATUS_RFNE (lift_shift_bit_num(3))
+#define SPI_STATUS_RFF (lift_shift_bit_num(4))
+#define SPI_STATUS_TXE (lift_shift_bit_num(5))
+#define SPI_STATUS_DCOL (lift_shift_bit_num(6))
+#define CACHE_LINE_SIZE (32)
+#define PUMP_DATA_NONE_MODE (0x00)
+#define PUMP_DATA_DMA_MODE (0x11)
+#define PUMP_DATA_ISR_MODE (0x22)
+#define PUMP_DATA_POLL_MODE (0x33)
+#define DMA_TRANS_GATE_LEVEL 1024
+#define SPI_DATA_REG_OFFSET (0x60)
+#define SPI_RX_ONLY_ONE_TIME_SIZE (0x10000)
+#define MAX_SG_LEN 128
+#if (SPI_RX_ONLY_ONE_TIME_SIZE > 2048)
+#define SG_ONE_TIME_MAX_SIZE 2048
+#else
+#define SG_ONE_TIME_MAX_SIZE SPI_RX_ONLY_ONE_TIME_SIZE
+#endif
+
+#define SPI_DATA_DIR_IN (0xaa)
+#define SPI_DATA_DIR_OUT (0xbb)
+#define SPI_DATA_DIR_DUOLEX (0xcc)
+#define RX_FIFO_MAX_LEN 256
+#define RX_FIFO_MIN_LEN 2
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type
+ * that only be used in this file here
+ ***************************************************************************/
+enum {
+ CONFIG_OK = 0, CONFIG_PARA_ERROR = lift_shift_bit_num(0),
+ //only for the set slave en/disable
+ CONFIG_BUSY = lift_shift_bit_num(1),
+ //only for write_read mode
+ WRITE_READ_OK = 0,
+ WRITE_READ_ERROR = lift_shift_bit_num(2),
+ WRITE_READ_TIME_OUT = lift_shift_bit_num(3),
+ //only for write only mode
+ WRITE_ONLY_OK = 0,
+ WRITE_ONLY_ERROR = lift_shift_bit_num(4),
+ WRITE_ONLY_TIME_OUT = lift_shift_bit_num(5),
+ //only for read only mode
+ READ_ONLY_OK = 0,
+ READ_ONLY_ERROR = lift_shift_bit_num(6),
+ READ_ONLY_TIME_OUT = lift_shift_bit_num(7),
+ //eeprom mode
+ EEPROM_OK = 0,
+ EEPROM_ERROR = lift_shift_bit_num(8),
+ EEPROM_TIME_OUT = lift_shift_bit_num(9),
+ /* if read/write/eeprom error,the error below
+ * could give you more info by reading the
+ * 'Spi_ReadTransferError' function
+ */
+ MULTI_MASTER_ERROR = lift_shift_bit_num(10),
+ TX_OVERFLOW_ERROR = lift_shift_bit_num(11),
+ RX_OVERFLOW_ERROR = lift_shift_bit_num(12),
+};
+
+//enable spi
+typedef enum enum_spi_enable {
+ SPI_DISABLE = 0,
+ SPI_ENABLE = (lift_shift_bit_num(0)),
+} spi_enable_e;
+
+//polarity
+typedef enum enum_spi_polarity {
+ SPI_POLARITY_LOW = 0,
+ SPI_POLARITY_HIGH = (lift_shift_bit_num(7)),
+ //bit pos
+ SPI_POLARITY_RANGE = (lift_shift_bit_num(7)),
+} spi_polarity_e;
+
+//phase
+typedef enum enum_spi_phase {
+ SPI_PHASE_RX_FIRST = 0,
+ SPI_PHASE_TX_FIRST = (lift_shift_bit_num(6)),
+ //bit pos
+ SPI_PHASE_RANGE = (lift_shift_bit_num(6)),
+} spi_phase_e;
+
+//frame format
+typedef enum enum_spi_format {
+ SPI_MOTOROLA_MODE = 0x00,
+ SPI_TI_MODE = 0x10,
+ SPI_MICROWIRE_MODE = 0x20,
+ //bit pos
+ SPI_FRAME_FORMAT_RANGE = 0x30,
+} spi_format_e;
+
+//data size
+typedef enum enum_spi_data_size {
+ SPI_DATA_SIZE_4BIT = 0x03,
+ SPI_DATA_SIZE_5BIT = 0x04,
+ SPI_DATA_SIZE_6BIT = 0x05,
+ SPI_DATA_SIZE_7BIT = 0x06,
+ SPI_DATA_SIZE_8BIT = 0x07,
+ SPI_DATA_SIZE_9BIT = 0x08,
+ SPI_DATA_SIZE_10BIT = 0x09,
+ SPI_DATA_SIZE_16BIT = 0x0f,
+ //bit pos
+ SPI_DATA_SIZE_RANGE = 0x0f,
+} spi_data_size_e;
+
+//transfer mode
+typedef enum enum_spi_transfer_mode {
+ SPI_TX_RX_MODE = 0x000,
+ SPI_ONLY_TX_MODE = 0x100,
+ SPI_ONLY_RX_MODE = 0x200,
+ SPI_EEPROM_MODE = 0x300,
+ //bit pos
+ SPI_TRANSFER_MODE_RANGE = 0x300,
+} spi_transfer_mode_e;
+
+//spi_irq
+typedef enum enum_spi_irq {
+ SPI_IRQ_TXEIM = (lift_shift_bit_num(0)),
+ SPI_IRQ_TXOIM = (lift_shift_bit_num(1)),
+ SPI_IRQ_RXUIM = (lift_shift_bit_num(2)),
+ SPI_IRQ_RXOIM = (lift_shift_bit_num(3)),
+ SPI_IRQ_RXFIM = (lift_shift_bit_num(4)),
+ SPI_IRQ_MSTIM = (lift_shift_bit_num(5)),
+ SPI_IRQ_ALL = 0x3f,
+} spi_irq_e;
+
+//spi_slave_port
+typedef enum enum_spi_slave {
+ SPI_SLAVE_PORT0 = (lift_shift_bit_num(0)),
+ SPI_SLAVE_PORT1 = (lift_shift_bit_num(1)),
+} spi_slave_e;
+
+//dma control
+typedef enum enum_spi_dma_control_mode {
+ SPI_DMA_RX_POS = (lift_shift_bit_num(0)),
+ SPI_DMA_TX_POS = (lift_shift_bit_num(1)),
+ //bit pos
+ SPI_DMA_CONTROL_RANGE = 0x03,
+} spi_dma_control_mode_e;
+
+//slave control
+typedef enum enum_spi_slave_mode {
+ SPI_SLAVE_EN = 0x00,
+ SPI_SLAVE_MODE_RANGE = 1 << 10,
+} spi_slave_mode_e;
+
+/*read wire mode*/
+typedef enum enum_spi_read_wire_mode {
+ STANDARD_READ = 0x00,
+ DUAL_OUTPUT = 0x01,
+ DUAL_IO = 0x02,
+ QUAD_OUTPUT = 0x03,
+ QUAD_IO = 0x04,
+} spi_read_wire_mode_e;
+
+/*program wire mode*/
+typedef enum enum_spi_prog_wire_mode {
+ STANDARD_PROG = 0x00,
+ QUAD_INPUT = 0x01,
+} spi_prog_wire_mode_e;
+
+/*ahb Xip config*/
+typedef enum enum_spi_xip_config {
+ XIP_DISABLE = 0,
+ XIP_ENABLE = 1,
+} spi_xip_config_e;
+
+/*ahb DPI config*/
+typedef enum enum_spi_dpi_config {
+ DPI_DISABLE = 0,
+ DPI_ENABLE = 1,
+} spi_dpi_config_e;
+
+/*ahb QPI config*/
+typedef enum enum_spi_qpi_config {
+ QPI_DISABLE = 0,
+ QPI_ENABLE = 1,
+} spi_qpi_config_e;
+
+struct fh_spi_reg {
+ u32 ctrl0;
+ u32 ctrl1;
+ u32 ssienr;
+ u32 mwcr;
+ u32 ser;
+ u32 baudr;
+ u32 txfltr;
+ u32 rxfltr;
+ u32 txflr;
+ u32 rxflr;
+ u32 sr;
+ u32 imr;
+ u32 isr;
+ u32 risr;
+ u32 txoicr;
+ u32 rxoicr;
+ u32 rxuicr;
+ u32 msticr;
+ u32 icr;
+ u32 dmacr;
+ u32 dmatdlr;
+ u32 dmardlr;
+ u32 idr;
+ u32 version;
+ u32 dr; /* Currently oper as 32 bits,
+ though only low 16 bits matters */
+ u32 rev[35];
+ u32 rx_sample_dly;
+ u32 ccfgr;
+ u32 opcr;
+ u32 timcr;
+ u32 bbar0;
+ u32 bbar1;
+};
+
+#define dw_readl(dw, name) \
+ __raw_readl(&(((struct fh_spi_reg *)dw->regs)->name))
+#define dw_writel(dw, name, val) \
+ __raw_writel((val), &(((struct fh_spi_reg *)dw->regs)->name))
+#define dw_readw(dw, name) \
+ __raw_readw(&(((struct fh_spi_reg *)dw->regs)->name))
+#define dw_writew(dw, name, val) \
+ __raw_writew((val), &(((struct fh_spi_reg *)dw->regs)->name))
+struct fh_spi_controller;
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+struct fh_spi_multi {
+ /*add multi*/
+ u32 max_wire_size;
+ u32 swap_max_size;
+ u32 active_wire_width;
+ u32 dir;
+ void (*fix_wire_mode)(struct fh_spi_controller *fh_spi);
+ void (*change_1_wire)(struct spi_master *p_master);
+ void (*change_2_wire)(struct spi_master *p_master, u32 dir);
+ void (*change_4_wire)(struct spi_master *p_master, u32 dir);
+ void (*swap_data_width)(struct fh_spi_controller *fh_spi, u32 reg_width);
+};
+void spic_multi_wire_init(struct spi_master * p_master);
+#endif
+
+#ifdef CONFIG_SPI_USE_DMA
+struct fh_spi_dma_channel_para {
+ u32 hs_no;
+ struct dma_chan *chan;
+ struct dma_slave_config cfg;
+ struct scatterlist sgl[MAX_SG_LEN];
+ u32 sgl_data_size[MAX_SG_LEN];
+ u32 actual_sgl_size;
+ struct dma_async_tx_descriptor *desc;
+ u32 complete_times;
+};
+
+struct fh_spi_dma {
+ /*u32 dumy_buff[4];*/
+ struct fh_spi_dma_channel_para rx;
+ struct completion done;
+ int (*dma_read)(struct fh_spi_controller *fh_spi);
+ int (*dma_write)(struct fh_spi_controller *fh_spi);
+ int (*dma_write_read)(struct fh_spi_controller *fh_spi);
+};
+void fh_spi_dma_init(struct fh_spi_controller *fh_spi);
+#endif
+
+struct fh_spi {
+ void * __iomem regs; /* vaddr of the control registers */
+ u32 id;
+ u32 irq;
+ u32 paddr;
+ u32 slave_port;
+ u32 fifo_len; /* depth of the FIFO buffer */
+ u32 max_freq; /* max bus freq supported */
+
+ /*use id u32 bus_num;*//*which bus*/
+ u32 num_cs; /* supported slave numbers */
+ u32 transfer_mode;
+ u32 active_cs_pin;
+ //copy from the user...
+ u32 tx_len;
+ u32 rx_len;
+ void *rx_buff;
+ void *tx_buff;
+ struct fh_spi_cs cs_data[SPI_MASTER_CONTROLLER_MAX_SLAVE];
+ struct fh_spi_platform_data *board_info;
+ char isr_name[16];
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ struct fh_spi_multi multi_para;
+#endif
+#ifdef CONFIG_SPI_USE_DMA
+ struct fh_spi_dma dma_para;
+#endif
+};
+
+struct fh_spi_controller {
+ //bind to master class
+ struct device *master_dev;
+
+ struct mutex lock;
+ //message queue
+ struct list_head queue;
+ struct platform_device *p_dev;
+ struct work_struct work;
+ struct workqueue_struct *workqueue;
+ struct spi_message *active_message;
+ struct spi_transfer *active_transfer;
+ struct fh_spi dwc;
+ struct spi_device *active_spi_dev;
+};
+
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+u32 Spi_Enable(struct fh_spi *dw, spi_enable_e enable);
+u32 Spi_ReadStatus(struct fh_spi *dw);
+u32 check_spi_sup_multi_wire(struct fh_spi_controller *fh_spi);
+u32 rx_only_fix_data_width(struct fh_spi_controller *fh_spi, u32 size);
+u32 Spi_RawIsrstatus(struct fh_spi *dw);
+u32 Spi_ContinueReadNum(struct fh_spi *dw, u32 num);
+u32 Spi_WriteData(struct fh_spi *dw, u32 data);
+u32 Spi_SetRxlevlel(struct fh_spi *dw, u32 level);
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+#endif
diff --git a/drivers/spi/fh_spi_dma.c b/drivers/spi/fh_spi_dma.c
new file mode 100644
index 00000000..59570e10
--- /dev/null
+++ b/drivers/spi/fh_spi_dma.c
@@ -0,0 +1,288 @@
+
+#include "fh_spi_common.h"
+
+static void Spi_SetDmaRxDataLevel(struct fh_spi *dw, u32 level)
+{
+ dw_writel(dw, dmardlr, level);
+}
+
+static void Spi_SetDmaControlEnable(struct fh_spi *dw,
+ spi_dma_control_mode_e enable_pos)
+{
+ u32 data;
+ data = dw_readl(dw, dmacr);
+ data |= enable_pos;
+ dw_writel(dw, dmacr, data);
+}
+
+static void Spi_SetDmaControlDisable(struct fh_spi *dw,
+ spi_dma_control_mode_e enable_pos)
+{
+ u32 data;
+ data = dw_readl(dw, dmacr);
+ data &= ~enable_pos;
+ dw_writel(dw, dmacr, data);
+}
+
+static bool fh_spi_dma_chan_filter(struct dma_chan *chan, void *param)
+{
+ int dma_channel = *(int *) param;
+ bool ret = false;
+
+ if (chan->chan_id == dma_channel)
+ ret = true;
+ return ret;
+}
+
+unsigned int fh_spi_dma_set_rx_config(struct fh_spi_controller *fh_spi,
+struct dma_slave_config *rx_config)
+{
+ unsigned int ret;
+
+ rx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ ret = SG_ONE_TIME_MAX_SIZE;
+ rx_config->src_addr = fh_spi->dwc.paddr + SPI_DATA_REG_OFFSET;
+ rx_config->slave_id = fh_spi->dwc.dma_para.rx.hs_no;
+ rx_config->src_maxburst = 8;
+ rx_config->dst_maxburst = 8;
+ rx_config->device_fc = false;
+ rx_config->direction = DMA_DEV_TO_MEM;
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if(check_spi_sup_multi_wire(fh_spi)){
+ rx_config->src_addr = fh_spi->dwc.paddr + 0x1000;
+ ret = min(SG_ONE_TIME_MAX_SIZE, 0x1000);
+ rx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ }
+#endif
+ return ret;
+}
+
+void fh_spi_dma_set_rx_src_width(struct dma_slave_config *rx_config, unsigned int data_width)
+{
+ if (data_width == 8)
+ rx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ else if (data_width == 16)
+ rx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ else if (data_width == 32)
+ rx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ else
+ BUG_ON(1);
+}
+
+void fh_spi_dma_set_rx_extra_para(struct fh_spi_controller *fh_spi,
+struct fh_dma_extra *p_ext_para)
+{
+#if 0
+ if (!!fh_spi->dwc.board_info->dma_protctl_enable) {
+ p_ext_para->protctl_flag = PROTCTL_ENABLE;
+ p_ext_para->protctl_data =
+ fh_spi->dwc.board_info->dma_protctl_data;
+ }
+
+ if (!!fh_spi->dwc.board_info->dma_master_sel_enable) {
+ p_ext_para->master_flag = MASTER_SEL_ENABLE;
+ p_ext_para->src_master =
+ fh_spi->dwc.board_info->dma_master_ctl_sel;
+ p_ext_para->dst_master =
+ fh_spi->dwc.board_info->dma_master_mem_sel;
+ }
+#endif
+ p_ext_para->dinc = FH_DMA_SLAVE_INC;
+ p_ext_para->sinc = FH_DMA_SLAVE_FIX;
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if(check_spi_sup_multi_wire(fh_spi)){
+ p_ext_para->sinc = FH_DMA_SLAVE_INC;
+ }
+#endif
+
+}
+
+static int dma_set_rx_para(struct fh_spi_controller *fh_spi,
+void (*call_back)(void *arg), unsigned int rx_para_size, unsigned int data_width)
+{
+ struct fh_dma_extra ext_para;
+ struct dma_slave_config *rx_config;
+ struct spi_transfer *t;
+ struct dma_chan *rxchan;
+ struct scatterlist *p_sca_list;
+ unsigned int sg_size = 0;
+ int i, xfer_len, one_sg_data_len;
+ unsigned char *temp_buf;
+ unsigned int one_time_size;
+ struct dma_async_tx_descriptor *p_desc = 0;
+
+ t = fh_spi->active_transfer;
+ rxchan = fh_spi->dwc.dma_para.rx.chan;
+ rx_config = &fh_spi->dwc.dma_para.rx.cfg;
+ memset(rx_config, 0, sizeof(struct dma_slave_config));
+ memset(&ext_para, 0, sizeof(struct fh_dma_extra));
+
+ one_time_size = fh_spi_dma_set_rx_config(fh_spi, rx_config);
+ fh_spi_dma_set_rx_src_width(rx_config, data_width);
+ xfer_len = rx_para_size;
+ temp_buf = (unsigned char *)t->rx_buf;
+ fh_spi_dma_set_rx_extra_para(fh_spi, &ext_para);
+
+ if (xfer_len >= one_time_size)
+ sg_size = xfer_len / one_time_size;
+
+ if (xfer_len % one_time_size)
+ sg_size++;
+
+ if (sg_size > MAX_SG_LEN) {
+ printk("%s_%d :: too large sg size:0x%x\n",
+ __func__, __LINE__, sg_size);
+ return -1;
+ }
+
+ p_sca_list = &fh_spi->dwc.dma_para.rx.sgl[0];
+ for (i = 0; i < sg_size; i++, p_sca_list++)
+ {
+ one_sg_data_len = min((u32)xfer_len, one_time_size);
+ xfer_len -= one_sg_data_len;
+ p_sca_list->dma_address = dma_map_single(
+ rxchan->dev->device.parent,
+ (void *)temp_buf, one_sg_data_len,
+ DMA_FROM_DEVICE);
+ fh_spi->dwc.dma_para.rx.sgl_data_size[i] = one_sg_data_len;
+ temp_buf += one_sg_data_len;
+ p_sca_list->length = one_sg_data_len;
+ }
+
+ dmaengine_slave_config(rxchan, rx_config);
+ p_desc = rxchan->device->device_prep_slave_sg(rxchan,
+ &fh_spi->dwc.dma_para.rx.sgl[0], sg_size, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
+ &ext_para);
+ BUG_ON(!p_desc);
+ fh_spi->dwc.dma_para.rx.actual_sgl_size = sg_size;
+ p_desc->callback = call_back;
+ p_desc->callback_param = fh_spi;
+ /*write back to host para*/
+ fh_spi->dwc.dma_para.rx.desc = p_desc;
+ return 0;
+}
+
+void unmap_dma_rx_sg(struct fh_spi_controller *fh_spi){
+ struct dma_chan *rxchan;
+ struct scatterlist *p_sca_list;
+ int i;
+
+ rxchan = fh_spi->dwc.dma_para.rx.chan;
+ p_sca_list = &fh_spi->dwc.dma_para.rx.sgl[0];
+ for(i = 0; i < fh_spi->dwc.dma_para.rx.actual_sgl_size; i++, p_sca_list++){
+ dma_unmap_single(rxchan->dev->device.parent,
+ p_sca_list->dma_address,
+ fh_spi->dwc.dma_para.rx.sgl_data_size[i], DMA_FROM_DEVICE);
+ }
+}
+
+static void fh_spi_rx_only_dma_done(void *arg)
+{
+ struct fh_spi_controller *fh_spi = (struct fh_spi_controller *) arg;
+ complete(&(fh_spi->dwc.dma_para.done));
+
+}
+
+static int dma_pump_rx_only_data(struct fh_spi_controller *fh_spi)
+{
+
+ struct spi_transfer *t;
+ struct dma_chan *rxchan;
+ int ret;
+ unsigned int temp_size;
+ unsigned int reg_width;
+ struct dma_async_tx_descriptor *p_desc;
+ u32 raw_isr;
+
+ t = fh_spi->active_transfer;
+ rxchan = fh_spi->dwc.dma_para.rx.chan;
+
+ init_completion(&fh_spi->dwc.dma_para.done);
+
+ temp_size = min(fh_spi->dwc.tx_len, (u32)SPI_RX_ONLY_ONE_TIME_SIZE);
+ reg_width = rx_only_fix_data_width(fh_spi, temp_size);
+
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if (reg_width > 8)
+ fh_spi->dwc.multi_para.swap_data_width(fh_spi, reg_width);
+#endif
+
+ ret = dma_set_rx_para(fh_spi, fh_spi_rx_only_dma_done, temp_size, reg_width);
+ if (ret != 0)
+ BUG_ON(1);
+ p_desc = fh_spi->dwc.dma_para.rx.desc;
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_SetDmaRxDataLevel(&fh_spi->dwc, 7);
+
+ Spi_ContinueReadNum(&fh_spi->dwc, temp_size / (reg_width / 8));
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+
+ p_desc->tx_submit(p_desc);
+ Spi_SetDmaControlEnable(&fh_spi->dwc, SPI_DMA_RX_POS);
+ Spi_WriteData(&fh_spi->dwc, 0xffffffff);
+
+ if (!(wait_for_completion_timeout(&fh_spi->dwc.dma_para.done, 20*HZ))) {
+ raw_isr = Spi_RawIsrstatus(&fh_spi->dwc);
+ pr_err("%s %d time out..spi raw status is %x\n",
+ __func__, __LINE__, raw_isr);
+ BUG_ON(1);
+ return -1;
+ }
+ if (t->rx_buf != NULL)
+ unmap_dma_rx_sg(fh_spi);
+
+ Spi_SetDmaControlDisable(&fh_spi->dwc, SPI_DMA_RX_POS);
+ /*here need to cal the data has been transfered ...
+ if we need to start a new transfer
+ then maybe i could recall the rx only func :)*/
+ fh_spi->dwc.rx_len += temp_size;
+ fh_spi->dwc.tx_len -= temp_size;
+ fh_spi->active_transfer->rx_buf += temp_size;
+
+#ifdef CONFIG_SPI_USE_MULTI_WIRE
+ if (reg_width > 8)
+ fh_spi->dwc.multi_para.swap_data_width(fh_spi, 8);
+#endif
+
+ return 0;
+}
+
+
+static int dma_pump_data_read(struct fh_spi_controller *fh_spi){
+ BUG_ON(fh_spi->dwc.transfer_mode != SPI_ONLY_RX_MODE);
+
+ do {
+ dma_pump_rx_only_data(fh_spi);
+ } while (fh_spi->dwc.tx_len != 0);
+
+ return 0;
+}
+
+
+void fh_spi_dma_init(struct fh_spi_controller *fh_spi){
+ int filter_no;
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ if (fh_spi->dwc.board_info->dma_transfer_enable != SPI_TRANSFER_USE_DMA)
+ return;
+
+ filter_no = fh_spi->dwc.board_info->rx_dma_channel;
+ fh_spi->dwc.dma_para.rx.chan = dma_request_channel(mask,
+ fh_spi_dma_chan_filter, &filter_no);
+
+ if (!fh_spi->dwc.dma_para.rx.chan) {
+ dev_err(&fh_spi->p_dev->dev,
+ "spi%d request dma channel error....\n",
+ fh_spi->dwc.id);
+ fh_spi->dwc.board_info->dma_transfer_enable = 0;
+ return;
+ }
+ fh_spi->dwc.dma_para.rx.hs_no = fh_spi->dwc.board_info->rx_handshake_num;
+ fh_spi->dwc.dma_para.dma_read = dma_pump_data_read;
+ fh_spi->dwc.dma_para.dma_write = NULL;
+ fh_spi->dwc.dma_para.dma_write_read = NULL;
+
+}
diff --git a/drivers/spi/fh_spi_multi_wire.c b/drivers/spi/fh_spi_multi_wire.c
new file mode 100644
index 00000000..b96526c5
--- /dev/null
+++ b/drivers/spi/fh_spi_multi_wire.c
@@ -0,0 +1,369 @@
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include "fh_spi_common.h"
+
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type
+ * that only be used in this file here
+ ***************************************************************************/
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static void reg_bit_process(u32 *data, u32 value, u32 mask);
+static int Spi_SetApbReadWireMode(struct fh_spi *dw, spi_read_wire_mode_e mode);
+static int Spi_SetXip(struct fh_spi *dw, spi_xip_config_e value);
+static int Spi_SetDPI(struct fh_spi *dw, spi_dpi_config_e value);
+static int Spi_SetSwap(struct fh_spi *dw, unsigned int value);
+static int Spi_SetWidth(struct fh_spi *dw, unsigned int value);
+static int Spi_SetQPI(struct fh_spi *dw, spi_qpi_config_e value);
+static int Spi_TimingConfigure(struct fh_spi *dw, u32 value);
+static void fh_spic_check_idle(struct fh_spi *dw);
+static void spic_bus_change_1_wire(struct spi_master *p_master);
+static void spic_bus_change_2_wire(struct spi_master *p_master, u32 dir);
+static void spic_bus_change_4_wire(struct spi_master *p_master, u32 dir);
+static void spic_swap_data_width(struct fh_spi_controller *fh_spi, u32 reg_width);
+static void spic_fix_wire_mode(struct fh_spi_controller *fh_spi);
+/*****************************************************************************
+ * Global variables section - Local
+ * define global variables(will be refered only in this file) here,
+ * static keyword should be used to limit scope of local variable to this file
+ * e.g.
+ * static uint8_t ufoo;
+ *****************************************************************************/
+
+/*add spic new code here below..*/
+static void reg_bit_process(u32 *data, u32 value, u32 mask)
+{
+ (*data) &= ~mask;
+ (*data) |= value;
+}
+
+static int Spi_SetApbReadWireMode(struct fh_spi *dw, spi_read_wire_mode_e mode)
+{
+ u32 data = dw_readl(dw, ccfgr);
+
+ switch (mode){
+ case STANDARD_READ:
+ reg_bit_process(&data, 0 << 8, 7 << 8);
+ reg_bit_process(&data, 0 << 2, 3 << 2);
+ reg_bit_process(&data, 0 << 0, 3 << 0);
+ reg_bit_process(&data, 0 << 4, 7 << 4);
+ break;
+
+ case DUAL_OUTPUT:
+ reg_bit_process(&data, 0 << 8, 7 << 8);
+ reg_bit_process(&data, 3 << 2, 3 << 2);
+ reg_bit_process(&data, 1 << 0, 3 << 0);
+ reg_bit_process(&data, 0 << 4, 7 << 4);
+ break;
+
+ case QUAD_OUTPUT:
+ reg_bit_process(&data, 0 << 8, 7 << 8);
+ reg_bit_process(&data, 3 << 2, 3 << 2);
+ reg_bit_process(&data, 2 << 0, 3 << 0);
+ reg_bit_process(&data, 0 << 4, 7 << 4);
+ break;
+ default:
+ printk("wrong mode now....\n");
+ }
+ data |= 1<<13;
+ dw_writel(dw, ccfgr, data);
+ return CONFIG_OK;
+}
+
+static int Spi_SetXip(struct fh_spi *dw, spi_xip_config_e value)
+{
+ u32 data = dw_readl(dw, ccfgr);
+ u32 data1 = dw_readl(dw, opcr);
+
+ if (value == XIP_ENABLE) {
+ reg_bit_process(&data, XIP_ENABLE << 11, 1 << 11);
+ reg_bit_process(&data1, 0x20 << 20, 0xff << 20);
+ } else if (value == XIP_DISABLE) {
+ reg_bit_process(&data, XIP_DISABLE << 11, 1 << 11);
+ reg_bit_process(&data1, 0xff << 20, 0xff << 20);
+ }
+ dw_writel(dw, ccfgr, data);
+ dw_writel(dw, opcr, data1);
+
+ return 0;
+}
+
+static int Spi_SetDPI(struct fh_spi *dw, spi_dpi_config_e value)
+{
+ u32 data = dw_readl(dw, opcr);
+
+ reg_bit_process(&data, value << 16, 1 << 16);
+ dw_writel(dw, opcr, data);
+ return 0;
+}
+
+static int Spi_SetSwap(struct fh_spi *dw, unsigned int value)
+{
+ u32 data;
+
+ Spi_Enable(dw, SPI_DISABLE);
+ data = dw_readl(dw, ccfgr);
+ data &= ~(1<<12);
+ data |= (value<<12);
+ dw_writel(dw, ccfgr, data);
+ Spi_Enable(dw, SPI_ENABLE);
+ return 0;
+}
+
+static int Spi_SetWidth(struct fh_spi *dw, unsigned int value)
+{
+ u32 data;
+ u32 ret;
+
+ Spi_Enable(dw, SPI_DISABLE);
+ data = dw_readl(dw, ctrl0);
+ ret = dw_readl(dw, ccfgr);
+ if (value == 32) {
+ ret |= 1<<16;
+ data &= ~(0x1f << 16);
+ data |= ((value - 1) << 16);
+ } else {
+ ret &= ~(1<<16);
+ data &= ~(0x0f << 0);
+ data |= ((value - 1) << 0);
+ }
+
+ dw_writel(dw, ctrl0, data);
+ dw_writel(dw, ccfgr, ret);
+ Spi_Enable(dw, SPI_ENABLE);
+ return 0;
+}
+
+static int Spi_SetQPI(struct fh_spi *dw, spi_qpi_config_e value)
+{
+ u32 data = dw_readl(dw, opcr);
+
+ reg_bit_process(&data, value << 17, 1 << 17);
+ dw_writel(dw, opcr, data);
+
+ return 0;
+}
+
+static int Spi_TimingConfigure(struct fh_spi *dw, u32 value)
+{
+ dw_writel(dw, timcr, value);
+ return 0;
+}
+
+static void fh_spic_check_idle(struct fh_spi *dw)
+{
+ u32 status;
+
+ status = Spi_ReadStatus(dw);
+ /*ahb rx fifo not empty..*/
+ BUG_ON((status & 1<<10) != 0);
+ /*ahb tx fifo empty..*/
+ BUG_ON((status & 1<<9) != 1<<9);
+ /*apb rx fifo*/
+ BUG_ON((status & 1<<3) != 0);
+ /*apb tx fifo*/
+ BUG_ON((status & 1<<2) != 1<<2);
+ /*shift not busy..*/
+ BUG_ON((status & 1) != 0);
+}
+
+
+static void spic_bus_change_1_wire(struct spi_master *p_master)
+{
+ struct fh_spi_controller *fh_spi;
+
+ fh_spi = spi_master_get_devdata(p_master);
+ fh_spi->dwc.multi_para.active_wire_width = ONE_WIRE_SUPPORT;
+ fh_spi->dwc.multi_para.dir = SPI_DATA_DIR_DUOLEX;
+ fh_spic_check_idle(&fh_spi->dwc);
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_SetApbReadWireMode(&fh_spi->dwc,STANDARD_READ);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+}
+
+static void spic_bus_change_2_wire(struct spi_master *p_master, u32 dir)
+{
+ struct fh_spi_controller *fh_spi;
+
+ fh_spi = spi_master_get_devdata(p_master);
+ fh_spi->dwc.multi_para.active_wire_width = DUAL_WIRE_SUPPORT;
+ fh_spi->dwc.multi_para.dir = dir;
+ fh_spic_check_idle(&fh_spi->dwc);
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_SetApbReadWireMode(&fh_spi->dwc,DUAL_OUTPUT);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+
+}
+
+static void spic_bus_change_4_wire(struct spi_master *p_master, u32 dir)
+{
+ struct fh_spi_controller *fh_spi;
+
+ fh_spi = spi_master_get_devdata(p_master);
+ fh_spi->dwc.multi_para.active_wire_width = QUAD_WIRE_SUPPORT;
+ fh_spi->dwc.multi_para.dir = dir;
+ fh_spic_check_idle(&fh_spi->dwc);
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_SetApbReadWireMode(&fh_spi->dwc,QUAD_OUTPUT);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+}
+
+static void spic_swap_data_width(struct fh_spi_controller *fh_spi, u32 reg_width)
+{
+ switch(reg_width) {
+ case 32:
+ Spi_SetSwap(&fh_spi->dwc, 1);
+ Spi_SetWidth(&fh_spi->dwc, 32);
+ break;
+
+ case 16:
+ Spi_SetSwap(&fh_spi->dwc, 1);
+ Spi_SetWidth(&fh_spi->dwc, 16);
+ break;
+
+ case 8:
+ Spi_SetSwap(&fh_spi->dwc, 0);
+ Spi_SetWidth(&fh_spi->dwc, 8);
+ break;
+ default :
+ BUG_ON(1);
+ }
+}
+
+static void spic_fix_wire_mode(struct fh_spi_controller *fh_spi)
+{
+ struct spi_master *spi_master;
+ struct spi_device *p_spi_dev;
+ struct spi_transfer *t;
+
+ p_spi_dev = fh_spi->active_spi_dev;
+ spi_master = p_spi_dev->master;
+ t = fh_spi->active_transfer;
+ /*first check tx and rx can't be have multi wire the same time...*/
+ if((t->tx_nbits & (SPI_NBITS_DUAL | SPI_NBITS_QUAD)) && ((t->rx_nbits & (SPI_NBITS_DUAL | SPI_NBITS_QUAD)))){
+ dev_err(&p_spi_dev->dev, "%s, tx_nbits : rx_nbits = %x : %x\n",
+ __func__,t->tx_nbits,t->rx_nbits);
+ BUG_ON(1);
+ }
+ if(t->tx_buf){
+ switch(t->tx_nbits){
+ case SPI_NBITS_DUAL:
+ //set dual out...
+ spic_bus_change_2_wire(spi_master,SPI_DATA_DIR_OUT);
+ break;
+ case SPI_NBITS_QUAD:
+ spic_bus_change_4_wire(spi_master,SPI_DATA_DIR_OUT);
+ //set quad out...
+ break;
+
+ default:
+ break;
+ }
+ }
+ if(t->rx_buf) {
+ switch(t->rx_nbits){
+ case SPI_NBITS_DUAL:
+ //set dual out...
+ spic_bus_change_2_wire(spi_master, SPI_DATA_DIR_IN);
+ break;
+ case SPI_NBITS_QUAD:
+ spic_bus_change_4_wire(spi_master, SPI_DATA_DIR_IN);
+ //set quad out...
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* first check if spi slave open as multi wire */
+ if (p_spi_dev->mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD)) {
+ /* check spi control hw multi info */
+ if((fh_spi->dwc.multi_para.active_wire_width &
+ (DUAL_WIRE_SUPPORT | QUAD_WIRE_SUPPORT))
+ && (fh_spi->dwc.multi_para.dir == SPI_DATA_DIR_OUT)) {
+ fh_spi->dwc.transfer_mode = SPI_ONLY_TX_MODE;
+ }
+ else if((fh_spi->dwc.multi_para.active_wire_width &
+ (DUAL_WIRE_SUPPORT | QUAD_WIRE_SUPPORT)) &&
+ (fh_spi->dwc.multi_para.dir == SPI_DATA_DIR_IN)) {
+ fh_spi->dwc.transfer_mode = SPI_ONLY_RX_MODE;
+ }
+ /*do not parse one wire..*/
+ }
+}
+
+u32 Spi_SetClk_Masken(struct fh_spi *dw, unsigned int value)
+{
+ u32 data = dw_readl(dw, ccfgr);
+
+ data &= ~(1<<15);
+ data |= (value<<15);
+ dw_writel(dw, ccfgr, data);
+ return 0;
+}
+
+void spic_multi_wire_init(struct spi_master * p_master)
+{
+ struct fh_spi_controller *fh_spi;
+
+ fh_spi = spi_master_get_devdata(p_master);
+ fh_spi->dwc.multi_para.max_wire_size = fh_spi->dwc.board_info->ctl_wire_support;
+ //multi support
+ /* the spi->mode bits understood by this driver: */
+ if (fh_spi->dwc.multi_para.max_wire_size == 4)
+ p_master->mode_bits = SPI_CPOL | SPI_CPHA |\
+ SPI_RX_QUAD | SPI_RX_DUAL;
+ else if (fh_spi->dwc.multi_para.max_wire_size == 2)
+ p_master->mode_bits = SPI_CPOL | SPI_CPHA |\
+ SPI_RX_DUAL;
+
+ fh_spi->dwc.multi_para.swap_max_size = CONFIG_SPI_SWAP_MAX_DATA_WIDTH;
+ fh_spi->dwc.multi_para.change_1_wire = spic_bus_change_1_wire;
+ fh_spi->dwc.multi_para.change_2_wire = spic_bus_change_2_wire;
+ fh_spi->dwc.multi_para.change_4_wire = spic_bus_change_4_wire;
+ fh_spi->dwc.multi_para.fix_wire_mode = spic_fix_wire_mode;
+ fh_spi->dwc.multi_para.swap_data_width = spic_swap_data_width;
+ Spi_Enable(&fh_spi->dwc, SPI_DISABLE);
+ Spi_SetXip(&fh_spi->dwc, XIP_DISABLE);
+ Spi_SetDPI(&fh_spi->dwc, DPI_DISABLE);
+ Spi_SetQPI(&fh_spi->dwc, QPI_DISABLE);
+ Spi_TimingConfigure(&fh_spi->dwc, 0x0);
+ Spi_SetApbReadWireMode(&fh_spi->dwc,STANDARD_READ);
+ Spi_SetClk_Masken(&fh_spi->dwc, 1);
+ Spi_SetRxlevlel(&fh_spi->dwc, fh_spi->dwc.fifo_len - 2);
+ Spi_Enable(&fh_spi->dwc, SPI_ENABLE);
+}
+
+u32 check_spi_sup_multi_wire(struct fh_spi_controller *fh_spi)
+{
+ if (fh_spi->dwc.id == 0)
+ return 1;
+ else
+ return 0;
+}
diff --git a/drivers/spi/fh_spi_slave.c b/drivers/spi/fh_spi_slave.c
new file mode 100644
index 00000000..5d670118
--- /dev/null
+++ b/drivers/spi/fh_spi_slave.c
@@ -0,0 +1,568 @@
+/*****************************************************************************
+ * Include Section
+ * add all #include here
+ *****************************************************************************/
+#include "fh_spi_common.h"
+#include <linux/kfifo.h>
+/*****************************************************************************
+ * Define section
+ * add all #define here
+ *****************************************************************************/
+#define KFIFO_SIZE 2048
+#define SPI_SLAVE_MAX_FIFO_SIZE 256
+#define SLAVE_SET_PHASE 1
+#define SLAVE_SET_POLARITY (SLAVE_SET_PHASE + 1)
+#define SLAVE_INIT_RX_FIFO (SLAVE_SET_POLARITY + 1)
+#define SLAVE_INIT_TX_FIFO (SLAVE_INIT_RX_FIFO + 1)
+#define SLAVE_GET_ERROR_STATUS (SLAVE_INIT_TX_FIFO + 1)
+#define MAX_SPI_SLAVES (8)
+/****************************************************************************
+ * ADT section
+ * add definition of user defined Data Type
+ * that only be used in this file here
+ ***************************************************************************/
+struct fh_spi_slave_controller {
+ spinlock_t lock;
+ struct platform_device *p_dev;
+ struct fh_spi dwc;
+ u32 cur_rx_len;
+ u32 cur_tx_len;
+ /* dev interface */
+ int major;
+ struct class *psClass;
+ struct device *psDev;
+
+ /* kfifo interface */
+ struct kfifo kfifo_in;
+ struct kfifo kfifo_out;
+};
+
+/******************************************************************************
+ * Function prototype section
+ * add prototypes for all functions called by this file,execepting those
+ * declared in header file
+ *****************************************************************************/
+static int fh_spi_slave_init_hw(struct fh_spi_slave_controller *fh_spi_slave,
+ struct fh_spi_platform_data *board_info);
+static u32 Spi_SetFrameFormat(struct fh_spi *dw, spi_format_e format);
+static u32 Spi_SetTransferMode(struct fh_spi *dw, spi_transfer_mode_e mode);
+static u32 Spi_SetPolarity(struct fh_spi *dw, spi_polarity_e polarity);
+static u32 Spi_SetPhase(struct fh_spi *dw, spi_phase_e phase);
+static u32 Spi_DisableIrq(struct fh_spi *dw, u32 irq);
+static u32 Spi_EnableIrq(struct fh_spi *dw, u32 irq);
+static u32 Spi_SetSlaveMode(struct fh_spi *dw, spi_slave_mode_e format);
+/*****************************************************************************
+ * Global variables section - Exported
+ * add declaration of global variables that will be exported here
+ * e.g.
+ * int8_t foo;
+ ****************************************************************************/
+static struct fh_spi_slave_controller *priv_array[MAX_SPI_SLAVES] = { NULL,
+NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+/*****************************************************************************
+
+ * static fun;
+ *****************************************************************************/
+static u32 Spi_SetFrameFormat(struct fh_spi *dw, spi_format_e format)
+{
+ u32 data = 0;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_FRAME_FORMAT_RANGE;
+ data |= format;
+ dw_writel(dw, ctrl0, data);
+
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetTransferMode(struct fh_spi *dw, spi_transfer_mode_e mode)
+{
+ u32 data = 0;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_TRANSFER_MODE_RANGE;
+ data |= mode;
+ dw_writel(dw, ctrl0, data);
+
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetPhase(struct fh_spi *dw, spi_phase_e phase)
+{
+ u32 data;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_PHASE_RANGE;
+ data |= phase;
+ dw_writel(dw, ctrl0, data);
+
+ return CONFIG_OK;
+}
+
+static u32 Spi_DisableIrq(struct fh_spi *dw, u32 irq)
+{
+ u32 data = 0;
+
+ data = dw_readl(dw, imr);
+ data &= ~irq;
+ dw_writel(dw, imr, data);
+
+ return CONFIG_OK;
+}
+
+static u32 Spi_EnableIrq(struct fh_spi *dw, u32 irq)
+{
+ u32 data = 0;
+
+ data = dw_readl(dw, imr);
+ data |= irq;
+ dw_writel(dw, imr, data);
+
+ return CONFIG_OK;
+}
+
+static u32 Spi_SetTxlevlel(struct fh_spi *dw, u32 level)
+{
+ dw_writel(dw, txfltr, level);
+ return CONFIG_OK;
+}
+
+static u32 Spi_ReadTxfifolevel(struct fh_spi *dw)
+{
+ return dw_readl(dw, txflr);
+}
+
+static u32 Spi_ReadRxfifolevel(struct fh_spi *dw)
+{
+ return dw_readl(dw, rxflr);
+}
+
+static u32 Spi_ReadRxlevlel(struct fh_spi *dw)
+{
+ return dw_readl(dw, rxfltr);
+}
+
+static u32 Spi_SetSlaveMode(struct fh_spi *dw, spi_slave_mode_e format)
+{
+ u32 data = 0;
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_SLAVE_MODE_RANGE;
+ data |= format;
+ dw_writel(dw, ctrl0, data);
+
+ return CONFIG_OK;
+}
+
+static u16 Spi_ReadData(struct fh_spi *dw)
+{
+ return dw_readw(dw, dr);
+}
+
+static u32 Spi_Isrstatus(struct fh_spi *dw)
+{
+ u32 data = dw_readl(dw, isr);
+ return data;
+}
+
+static int spi_slave_open(struct inode *inode, struct file *filp)
+{
+ int i, ret = 0;
+ struct fh_spi_slave_controller *fh_spi_slave;
+
+ for (i = 0; i < MAX_SPI_SLAVES; i++) {
+ if (priv_array[i] && MKDEV(priv_array[i]->major, 0) == inode->i_rdev) {
+ filp->private_data = priv_array[i];
+ break;
+ }
+ }
+
+ if (i == MAX_SPI_SLAVES)
+ return -ENXIO;
+
+ fh_spi_slave = priv_array[i];
+ kfifo_reset(&fh_spi_slave->kfifo_in);
+ kfifo_reset(&fh_spi_slave->kfifo_out);
+ return ret;
+}
+
+static ssize_t spi_slave_read(struct file *filp, char *buf, size_t count,
+ loff_t *f_pos)
+{
+ int ret;
+ unsigned int copied;
+ struct fh_spi_slave_controller *fh_spi_slave;
+ fh_spi_slave = (struct fh_spi_slave_controller *)filp->private_data;
+
+ if (kfifo_is_empty(&fh_spi_slave->kfifo_out))
+ return -EFAULT;
+
+ ret = kfifo_to_user(&fh_spi_slave->kfifo_out, buf, count, &copied);
+ if (ret == 0) {
+ fh_spi_slave->cur_rx_len = copied;
+ return copied;
+ }else
+ return ret;
+}
+
+static void spi_slave_isr_tx_data(struct fh_spi_slave_controller *fh_spi_slave)
+{
+ Spi_SetTxlevlel(&fh_spi_slave->dwc, fh_spi_slave->dwc.fifo_len - 5);
+ Spi_EnableIrq(&fh_spi_slave->dwc, SPI_IRQ_TXEIM);
+}
+
+static ssize_t spi_slave_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ int ret;
+ unsigned int copied;
+ struct fh_spi_slave_controller *fh_spi_slave;
+ fh_spi_slave = (struct fh_spi_slave_controller *) filp->private_data;
+
+ if (kfifo_is_full(&fh_spi_slave->kfifo_in))
+ return -EFAULT;
+
+ ret = kfifo_from_user(&fh_spi_slave->kfifo_in, buf, count, &copied);
+ if (ret == 0) {
+ fh_spi_slave->cur_tx_len = copied;
+ spi_slave_isr_tx_data(fh_spi_slave);
+ return copied;
+ } else
+ return ret;
+}
+
+long spi_slave_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int err = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ case SLAVE_SET_PHASE:
+ break;
+ case SLAVE_SET_POLARITY:
+ break;
+ case SLAVE_INIT_RX_FIFO:
+ break;
+ case SLAVE_INIT_TX_FIFO:
+ break;
+ case SLAVE_GET_ERROR_STATUS:
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+static int spi_slave_release(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+ return ret;
+}
+
+static struct file_operations spi_slave_fops = {
+ .open = spi_slave_open,
+ .read = spi_slave_read,
+ .write = spi_slave_write,
+ .unlocked_ioctl = spi_slave_ioctl,
+ .release = spi_slave_release,
+};
+
+static inline u32 tx_max(struct fh_spi_slave_controller *fh_spi_slave)
+{
+ u32 hw_tx_level;
+
+ hw_tx_level = Spi_ReadTxfifolevel(&fh_spi_slave->dwc);
+ hw_tx_level = fh_spi_slave->dwc.fifo_len - hw_tx_level;
+
+ return hw_tx_level;
+}
+
+static inline u32 rx_max(struct fh_spi_slave_controller *fh_spi)
+{
+ u32 hw_rx_level;
+
+ hw_rx_level = Spi_ReadRxfifolevel(&fh_spi->dwc);
+
+ return hw_rx_level;
+}
+
+static void fh_spi_slave_check_fifo_depth(struct fh_spi_slave_controller *fh_spi)
+{
+ u32 w_i, r_i, ori;
+
+ ori = Spi_ReadRxlevlel(&fh_spi->dwc);
+ for (r_i = w_i = RX_FIFO_MIN_LEN; w_i < RX_FIFO_MAX_LEN; r_i++) {
+ Spi_SetRxlevlel(&fh_spi->dwc, ++w_i);
+ if (r_i == Spi_ReadRxlevlel(&fh_spi->dwc))
+ break;
+ }
+
+ fh_spi->dwc.fifo_len = r_i + 1;
+}
+
+static void spi_slave_process_tx_isr(struct fh_spi_slave_controller *fh_spi_slave)
+{
+
+ u8 tx_buff[SPI_SLAVE_MAX_FIFO_SIZE] = { 0 };
+ int kfifo_tx_size, hw_tx_size, trans_size;
+ u16 data;
+ int i;
+ int temp;
+
+ kfifo_tx_size = kfifo_len(&fh_spi_slave->kfifo_in);
+ hw_tx_size = tx_max(fh_spi_slave);
+ trans_size = min(kfifo_tx_size, hw_tx_size);
+ temp = kfifo_out(&fh_spi_slave->kfifo_in, tx_buff, trans_size);
+
+ for (i = 0; i < trans_size; i++) {
+ data = tx_buff[i];
+ Spi_WriteData(&fh_spi_slave->dwc, data);
+ }
+ fh_spi_slave->cur_tx_len -= trans_size;
+ if (fh_spi_slave->cur_tx_len == 0)
+ Spi_DisableIrq(&fh_spi_slave->dwc, SPI_IRQ_TXEIM);
+
+}
+
+static void spi_slave_process_rx_isr(
+ struct fh_spi_slave_controller *fh_spi_slave)
+{
+ int hw_rx_size;
+ int i;
+ u16 data;
+
+ hw_rx_size = rx_max(fh_spi_slave);
+ for (i = 0; i < hw_rx_size; i++) {
+ data = Spi_ReadData(&fh_spi_slave->dwc);
+ kfifo_in(&fh_spi_slave->kfifo_out, &data, 1);
+ }
+}
+
+static irqreturn_t fh_spi_slave_irq(int irq, void *dev_id)
+{
+ struct fh_spi_slave_controller *fh_spi_slave;
+ u32 isr_status;
+ u32 raw_status;
+
+ fh_spi_slave = (struct fh_spi_slave_controller *) dev_id;
+ isr_status = Spi_Isrstatus(&fh_spi_slave->dwc);
+ raw_status = Spi_RawIsrstatus(&fh_spi_slave->dwc);
+ if (raw_status & (1<<3))
+ pr_err("[FH_SPI_S_ERROR]: rx overflow....\n");
+
+ if (isr_status & SPI_IRQ_TXEIM)
+ spi_slave_process_tx_isr(fh_spi_slave);
+
+ if (isr_status & SPI_IRQ_RXFIM)
+ spi_slave_process_rx_isr(fh_spi_slave);
+
+ return IRQ_HANDLED;
+}
+
+static int fh_spi_slave_init_hw(struct fh_spi_slave_controller *fh_spi_slave,
+ struct fh_spi_platform_data *board_info)
+{
+ int status;
+
+ fh_spi_slave_check_fifo_depth(fh_spi_slave);
+
+ fh_spi_slave->dwc.transfer_mode = SPI_TX_RX_MODE;
+ do {
+ status = Spi_ReadStatus(&fh_spi_slave->dwc);
+ } while (status & 0x01);
+
+ Spi_Enable(&fh_spi_slave->dwc, SPI_DISABLE);
+ Spi_SetFrameFormat(&fh_spi_slave->dwc, SPI_MOTOROLA_MODE);
+ Spi_SetTransferMode(&fh_spi_slave->dwc, fh_spi_slave->dwc.transfer_mode);
+ Spi_SetPolarity(&fh_spi_slave->dwc, SPI_POLARITY_HIGH);
+ Spi_SetPhase(&fh_spi_slave->dwc, SPI_PHASE_RX_FIRST);
+ Spi_SetRxlevlel(&fh_spi_slave->dwc, 0);
+ Spi_SetSlaveMode(&fh_spi_slave->dwc, SPI_SLAVE_EN);
+ Spi_DisableIrq(&fh_spi_slave->dwc, SPI_IRQ_ALL);
+ Spi_EnableIrq(&fh_spi_slave->dwc, SPI_IRQ_RXFIM);
+ Spi_Enable(&fh_spi_slave->dwc, SPI_ENABLE);
+
+ return 0;
+}
+
+static u32 Spi_SetPolarity(struct fh_spi *dw, spi_polarity_e polarity)
+{
+ u32 data;
+
+ data = dw_readl(dw, ctrl0);
+ data &= ~(u32) SPI_POLARITY_RANGE;
+ data |= polarity;
+ dw_writel(dw, ctrl0, data);
+ return CONFIG_OK;
+}
+
+static int fh_spi_slave_probe(struct platform_device *dev)
+{
+ int err = 0;
+ int major_id;
+ struct resource *p_res;
+ struct clk *clk;
+ char spi_slave_name[32] = {0};
+ char spi_slave_class_name[32] = {0};
+ struct fh_spi_slave_controller *fh_spi_slave;
+ struct fh_spi_platform_data *spi_platform_info;
+
+ spi_platform_info = (struct fh_spi_platform_data *)dev->dev.platform_data;
+ if (spi_platform_info == NULL) {
+ dev_err(&dev->dev, "%s, spi slave platform data null.\n",
+ __func__);
+ err = -ENODEV;
+ return err;
+ }
+
+ fh_spi_slave = kzalloc(sizeof(struct fh_spi_slave_controller), GFP_KERNEL);
+ if (!fh_spi_slave) {
+ dev_err(&dev->dev, "malloc spi slave control mem not enough\n");
+ err = -ENOMEM;
+ return err;
+ }
+
+ p_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!p_res) {
+ dev_err(&dev->dev, "%s, spi slave ioresource error. \n",
+ __func__);
+ err = -ENODEV;
+ goto dev_free;
+ }
+
+ fh_spi_slave->dwc.id = spi_platform_info->bus_no;
+ fh_spi_slave->dwc.regs = ioremap(p_res->start, resource_size(p_res));
+ fh_spi_slave->dwc.paddr = p_res->start;
+ fh_spi_slave->dwc.irq = platform_get_irq(dev, 0);
+ fh_spi_slave->dwc.irq = irq_create_mapping(NULL, fh_spi_slave->dwc.irq);
+ sprintf(fh_spi_slave->dwc.isr_name, "spi-slave-%d", dev->id);
+
+ if (!fh_spi_slave->dwc.irq) {
+ pr_err("%s: ERROR: getting resource failed"
+ "cannot get IORESOURCE_IRQ\n", __func__);
+ err = -ENXIO;
+ goto dev_free;
+ }
+
+ err = request_irq(fh_spi_slave->dwc.irq, fh_spi_slave_irq, 0, fh_spi_slave->dwc.isr_name,
+ fh_spi_slave);
+ if (err) {
+ dev_dbg(&dev->dev, "request_irq failed, %d\n", err);
+ goto irqmapping_free;
+ }
+
+ spi_platform_info->bus_no = dev->id;
+ priv_array[dev->id] = fh_spi_slave;
+ spin_lock_init(&fh_spi_slave->lock);
+
+ clk = clk_get(NULL, spi_platform_info->clk_name);
+ if (IS_ERR(clk)) {
+ dev_err(&fh_spi_slave->p_dev->dev, "cannot find the spi-slave%d clk.\n",
+ fh_spi_slave->dwc.id);
+ err = PTR_ERR(clk);
+ goto irqmapping_free;
+ }
+ clk_set_rate(clk, SPI_DEFAULT_CLK);
+ clk_prepare_enable(clk);
+
+ fh_spi_slave->dwc.board_info = spi_platform_info;
+ err = fh_spi_slave_init_hw(fh_spi_slave, spi_platform_info);
+ if (err)
+ goto irqmapping_free;
+
+ sprintf(spi_slave_name, "fh_spi_slave_%d", dev->id);
+ sprintf(spi_slave_class_name, "fh_spi_slave_class_%d", dev->id);
+
+ major_id = register_chrdev(0, spi_slave_name, &spi_slave_fops);
+ if (major_id <= 0) {
+ err = -EIO;
+ dev_err(&fh_spi_slave->p_dev->dev, "cannot register spi slave_%d char dev..\n",
+ fh_spi_slave->dwc.id);
+ goto irqmapping_free;
+ } else
+ fh_spi_slave->major = major_id;
+
+
+ fh_spi_slave->psClass = class_create(THIS_MODULE, spi_slave_class_name);
+ if (IS_ERR(fh_spi_slave->psClass)) {
+ err = -EIO;
+ dev_err(&fh_spi_slave->p_dev->dev, "%s: Unable to create class\n", __FILE__);
+ goto irqmapping_free;
+ }
+
+ fh_spi_slave->psDev = device_create(fh_spi_slave->psClass,
+ NULL,
+ MKDEV(major_id, 0),
+ fh_spi_slave,
+ spi_slave_name);
+ if (IS_ERR(fh_spi_slave->psDev)) {
+ err = -EIO;
+ dev_err(&fh_spi_slave->p_dev->dev,"Error: %s: Unable to create device\n", __FILE__);
+ goto irqmapping_free;
+ }
+
+ if (kfifo_alloc(
+ &fh_spi_slave->kfifo_in,
+ KFIFO_SIZE,
+ GFP_KERNEL)) {
+ err = -EIO;
+ dev_err(&fh_spi_slave->p_dev->dev,"Error: %s: Unable to alloc kfifo..\n", __FILE__);
+ goto irqmapping_free;
+ }
+
+ if (kfifo_alloc(&fh_spi_slave->kfifo_out,
+ KFIFO_SIZE,
+ GFP_KERNEL)) {
+ err = -EIO;
+ dev_err(&fh_spi_slave->p_dev->dev,"Error: %s: Unable to alloc kfifo..\n", __FILE__);
+ goto irqmapping_free;
+ }
+
+ dev_info(&dev->dev, "FH Spi Slave probe successfully\n");
+
+ return 0;
+
+irqmapping_free:
+ free_irq(fh_spi_slave->dwc.irq, fh_spi_slave);
+dev_free:
+ kfree(fh_spi_slave);
+
+ return err;
+}
+
+static int fh_spi_slave_remove(struct platform_device *dev)
+{
+ return 0;
+}
+
+static const struct of_device_id fh_spi_slave_of_match[] = {
+ {.compatible = "fh,fh-spi-slave",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fh_spi_slave_of_match);
+
+static struct platform_driver fh_spi_slave_driver = {
+ .driver = {
+ .name = "fh_spi_slave",
+ .of_match_table = fh_spi_slave_of_match,
+ },
+ .probe = fh_spi_slave_probe,
+ .remove = fh_spi_slave_remove,
+};
+
+static int fh_spi_slave_init(void)
+{
+ return platform_driver_register(&fh_spi_slave_driver);
+}
+
+static void fh_spi_slave_exit(void)
+{
+ platform_driver_unregister(&fh_spi_slave_driver);
+}
+
+module_init(fh_spi_slave_init);
+module_exit(fh_spi_slave_exit);
+MODULE_AUTHOR("yu.zhang <zhangy@fullhan.com>");
+MODULE_DESCRIPTION("DUOBAO SPI SLAVE driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c2e85e23..80bf0318 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -53,7 +53,7 @@ static void spidev_release(struct device *dev)
spi_master_put(spi->master);
kfree(spi);
}
-
+#ifndef CONFIG_SPI_TINY_MEM
static ssize_t
modalias_show(struct device *dev, struct device_attribute *a, char *buf)
{
@@ -240,7 +240,7 @@ static const struct attribute_group *spi_master_groups[] = {
&spi_master_statistics_group,
NULL,
};
-
+#endif
void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
struct spi_transfer *xfer,
struct spi_master *master)
@@ -325,7 +325,9 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
struct bus_type spi_bus_type = {
.name = "spi",
+#ifndef CONFIG_SPI_TINY_MEM
.dev_groups = spi_dev_groups,
+#endif
.match = spi_match_device,
.uevent = spi_uevent,
};
@@ -338,6 +340,7 @@ static int spi_drv_probe(struct device *dev)
struct spi_device *spi = to_spi_device(dev);
int ret;
+ spi->sample_delay = 1;
ret = of_clk_set_defaults(dev->of_node, false);
if (ret)
return ret;
@@ -710,6 +713,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
struct sg_table *sgt, void *buf, size_t len,
enum dma_data_direction dir)
{
+#ifndef CONFIG_SPI_TINY_MEM
const bool vmalloced_buf = is_vmalloc_addr(buf);
unsigned int max_seg_size = dma_get_max_seg_size(dev);
#ifdef CONFIG_HIGHMEM
@@ -780,21 +784,24 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
}
sgt->nents = ret;
-
+#endif
return 0;
}
static void spi_unmap_buf(struct spi_master *master, struct device *dev,
struct sg_table *sgt, enum dma_data_direction dir)
{
+#ifndef CONFIG_SPI_TINY_MEM
if (sgt->orig_nents) {
dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir);
sg_free_table(sgt);
}
+#endif
}
static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
{
+#ifndef CONFIG_SPI_TINY_MEM
struct device *tx_dev, *rx_dev;
struct spi_transfer *xfer;
int ret;
@@ -837,12 +844,13 @@ static int __spi_map_msg(struct spi_master *master, struct spi_message *msg)
}
master->cur_msg_mapped = true;
-
+#endif
return 0;
}
static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
{
+#ifndef CONFIG_SPI_TINY_MEM
struct spi_transfer *xfer;
struct device *tx_dev, *rx_dev;
@@ -866,6 +874,7 @@ static int __spi_unmap_msg(struct spi_master *master, struct spi_message *msg)
spi_unmap_buf(master, rx_dev, &xfer->rx_sg, DMA_FROM_DEVICE);
spi_unmap_buf(master, tx_dev, &xfer->tx_sg, DMA_TO_DEVICE);
}
+#endif
return 0;
}
@@ -1018,7 +1027,7 @@ static int spi_transfer_one_message(struct spi_master *master,
ms = UINT_MAX;
ms = wait_for_completion_timeout(&master->xfer_completion,
- msecs_to_jiffies(ms));
+ msecs_to_jiffies(ms));
}
if (ms == 0) {
@@ -1778,7 +1787,9 @@ static struct class spi_master_class = {
.name = "spi_master",
.owner = THIS_MODULE,
.dev_release = spi_master_release,
- .dev_groups = spi_master_groups,
+#ifndef CONFIG_SPI_TINY_MEM
+ .dev_groups = spi_master_groups,
+#endif
};
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
index e389009f..026fc731 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
@@ -70,6 +70,36 @@ static const struct mtd_ooblayout_ops spinand_oob_64_ops = {
.ecc = spinand_ooblayout_64_ecc,
.free = spinand_ooblayout_64_free,
};
+
+static int spinand_ooblayout_128_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section > 8)
+ return -ERANGE;
+
+ oobregion->offset = (section * 8) + 64;
+ oobregion->length = 8;
+
+ return 0;
+}
+
+static int spinand_ooblayout_128_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section > 8)
+ return -ERANGE;
+
+ oobregion->offset = 1;
+ oobregion->length = 63;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops spinand_oob_128_ops = {
+ .ecc = spinand_ooblayout_128_ecc,
+ .free = spinand_ooblayout_128_free,
+};
+
#endif
/**
@@ -890,9 +920,9 @@ static int spinand_probe(struct spi_device *spi_nand)
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
chip->ecc.mode = NAND_ECC_HW;
- chip->ecc.size = 0x200;
- chip->ecc.bytes = 0x6;
- chip->ecc.steps = 0x4;
+ chip->ecc.size = 0x100;
+ chip->ecc.bytes = 0x8;
+ chip->ecc.steps = 0x8;
chip->ecc.strength = 1;
chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
@@ -913,7 +943,7 @@ static int spinand_probe(struct spi_device *spi_nand)
chip->read_byte = spinand_read_byte;
chip->cmdfunc = spinand_cmdfunc;
chip->waitfunc = spinand_wait;
- chip->options |= NAND_CACHEPRG;
+ chip->options |= (NAND_CACHEPRG | NAND_NO_SUBPAGE_WRITE);
chip->select_chip = spinand_select_chip;
mtd = nand_to_mtd(chip);
@@ -921,14 +951,13 @@ static int spinand_probe(struct spi_device *spi_nand)
dev_set_drvdata(&spi_nand->dev, mtd);
mtd->dev.parent = &spi_nand->dev;
- mtd->oobsize = 64;
+ mtd->oobsize = 128;
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
- mtd_set_ooblayout(mtd, &spinand_oob_64_ops);
+ mtd_set_ooblayout(mtd, &spinand_oob_128_ops);
#endif
if (nand_scan(mtd, 1))
return -ENXIO;
-
return mtd_device_register(mtd, NULL, 0);
}
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index 98f75e58..280e086b 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -26,17 +26,6 @@
#include "iscsi_target_nego.h"
#include "iscsi_target_auth.h"
-static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len)
-{
- int j = DIV_ROUND_UP(len, 2), rc;
-
- rc = hex2bin(dst, src, j);
- if (rc < 0)
- pr_debug("CHAP string contains non hex digit symbols\n");
-
- dst[j] = '\0';
- return j;
-}
static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
{
@@ -59,7 +48,7 @@ static void chap_gen_challenge(
memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
get_random_bytes(chap->challenge, CHAP_CHALLENGE_LENGTH);
- chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
+ bin2hex(challenge_asciihex, chap->challenge,
CHAP_CHALLENGE_LENGTH);
/*
* Set CHAP_C, and copy the generated challenge into c_str.
@@ -241,8 +230,16 @@ static int chap_server_compute_md5(
goto out;
}
+ if (strlen(chap_r) != MD5_SIGNATURE_SIZE * 2) {
+ pr_err("Malformaed CHAP_R\n");
+ goto out;
+ }
+ if (hex2bin(client_digest, chap_r, MD5_SIGNATURE_SIZE) < 0) {
+ pr_err("Malformaed CHAP_R\n");
+ goto out;
+ }
+
pr_debug("[server] Got CHAP_R=%s\n", chap_r);
- chap_string_to_hex(client_digest, chap_r, strlen(chap_r));
tfm = crypto_alloc_shash("md5", 0, 0);
if (IS_ERR(tfm)) {
@@ -286,7 +283,7 @@ static int chap_server_compute_md5(
goto out;
}
- chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE);
+ bin2hex(response, server_digest, MD5_SIGNATURE_SIZE);
pr_debug("[server] MD5 Server Digest: %s\n", response);
if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) {
@@ -341,9 +338,7 @@ static int chap_server_compute_md5(
pr_err("Could not find CHAP_C.\n");
goto out;
}
- pr_debug("[server] Got CHAP_C=%s\n", challenge);
- challenge_len = chap_string_to_hex(challenge_binhex, challenge,
- strlen(challenge));
+ challenge_len = DIV_ROUND_UP(strlen(challenge), 2);
if (!challenge_len) {
pr_err("Unable to convert incoming challenge\n");
goto out;
@@ -352,6 +347,11 @@ static int chap_server_compute_md5(
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
goto out;
}
+ if (hex2bin(challenge_binhe, challenge, challenge_len) < 0) {
+ pr_err("Malformed CHAP_C\n");
+ goto out;
+ }
+ pr_debug*("[server] Got CHAP_C=%s\n", challenge);
/*
* During mutual authentication, the CHAP_C generated by the
* initiator must not match the original CHAP_C generated by
@@ -405,7 +405,7 @@ static int chap_server_compute_md5(
/*
* Convert response from binary hex to ascii hext.
*/
- chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE);
+ bin2hex(response, digest, MD5_SIGNATURE_SIZE);
*nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s",
response);
*nr_out_len += 1;
diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
new file mode 100644
index 00000000..a6df12d8
--- /dev/null
+++ b/drivers/tee/Kconfig
@@ -0,0 +1,19 @@
+# Generic Trusted Execution Environment Configuration
+config TEE
+ tristate "Trusted Execution Environment support"
+ depends on HAVE_ARM_SMCCC || COMPILE_TEST
+ select DMA_SHARED_BUFFER
+ select GENERIC_ALLOCATOR
+ help
+ This implements a generic interface towards a Trusted Execution
+ Environment (TEE).
+
+if TEE
+
+menu "TEE drivers"
+
+source "drivers/tee/optee/Kconfig"
+
+endmenu
+
+endif
diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
new file mode 100644
index 00000000..24d516fc
--- /dev/null
+++ b/drivers/tee/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_TEE) += tee.o
+tee-objs += tee_core.o
+tee-objs += tee_shm.o
+tee-objs += tee_shm_pool.o
+obj-$(CONFIG_OPTEE) += optee/
+obj-$(CONFIG_TEE) += tee_api/
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
new file mode 100644
index 00000000..4728b591
--- /dev/null
+++ b/drivers/tee/optee/Kconfig
@@ -0,0 +1,22 @@
+# OP-TEE Trusted Execution Environment Configuration
+config OPTEE
+ tristate "OP-TEE"
+ depends on HAVE_ARM_SMCCC
+ help
+ This implements the OP-TEE Trusted Execution Environment (TEE)
+ driver.
+
+config OPTEE_SHM_NUM_PRIV_PAGES
+ int "Private Shared Memory Pages"
+ default 1
+ depends on OPTEE
+ help
+ This sets the number of private shared memory pages to be
+ used by OP-TEE TEE driver.
+
+config OPTEE_BENCHMARK
+ bool "OP-TEE Benchmark (EXPERIMENTAL)"
+ depends on OPTEE
+ help
+ This enables benchmarking feature in the OP-TEE Trusted
+ Execution Environment (TEE) driver.
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
new file mode 100644
index 00000000..68617585
--- /dev/null
+++ b/drivers/tee/optee/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_OPTEE) += optee.o
+optee-objs += core.o
+optee-objs += call.o
+optee-objs += rpc.o
+optee-objs += supp.o
+optee-objs += shm_pool.o
+optee-objs += bench.o
diff --git a/drivers/tee/optee/bench.c b/drivers/tee/optee/bench.c
new file mode 100644
index 00000000..9e73b2fb
--- /dev/null
+++ b/drivers/tee/optee/bench.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/smp.h>
+#include "optee_bench.h"
+
+/*
+ * Specific defines for ARM performance timers
+ */
+/* aarch32 */
+#define OPTEE_BENCH_DEF_OPTS (1 | 16)
+#define OPTEE_BENCH_DEF_OVER 0x8000000f
+/* enable 64 divider for CCNT */
+#define OPTEE_BENCH_DIVIDER_OPTS (OPTEE_BENCH_DEF_OPTS | 8)
+
+/* aarch64 */
+#define OPTEE_BENCH_ARMV8_PMCR_MASK 0x3f
+#define OPTEE_BENCH_ARMV8_PMCR_E (1 << 0) /* Enable all counters */
+#define OPTEE_BENCH_ARMV8_PMCR_P (1 << 1) /* Reset all counters */
+#define OPTEE_BENCH_ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */
+#define OPTEE_BENCH_ARMV8_PMCR_D (1 << 3) /* 64 divider */
+
+#define OPTEE_BENCH_ARMV8_PMUSERENR_EL0 (1 << 0) /* EL0 access enable */
+#define OPTEE_BENCH_ARMV8_PMUSERENR_CR (1 << 2) /* CCNT read enable */
+
+struct optee_ts_global *optee_bench_ts_global;
+struct rw_semaphore optee_bench_ts_rwsem;
+
+#ifdef CONFIG_OPTEE_BENCHMARK
+static inline u32 armv8pmu_pmcr_read(void)
+{
+ u32 val = 0;
+
+ asm volatile("mrs %0, pmcr_el0" : "=r"(val));
+
+ return (u32)val;
+}
+
+static inline void armv8pmu_pmcr_write(u32 val)
+{
+ val &= OPTEE_BENCH_ARMV8_PMCR_MASK;
+ asm volatile("msr pmcr_el0, %0" :: "r"((u64)val));
+}
+
+static inline u64 read_ccounter(void)
+{
+ u64 ccounter;
+
+#ifdef __aarch64__
+ asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(ccounter));
+#else
+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(ccounter));
+#endif
+
+ return ccounter * OPTEE_BENCH_DIVIDER;
+}
+
+static void optee_pmu_setup(void *data)
+{
+#ifdef __aarch64__
+ /* Enable EL0 access to PMU counters. */
+ asm volatile("msr pmuserenr_el0, %0" :: "r"((u64)
+ OPTEE_BENCH_ARMV8_PMUSERENR_EL0 |
+ OPTEE_BENCH_ARMV8_PMUSERENR_CR));
+ /* Enable PMU counters */
+ armv8pmu_pmcr_write(OPTEE_BENCH_ARMV8_PMCR_P |
+ OPTEE_BENCH_ARMV8_PMCR_C |
+ OPTEE_BENCH_ARMV8_PMCR_D);
+ asm volatile("msr pmcntenset_el0, %0" :: "r"((u64)(1 << 31)));
+ armv8pmu_pmcr_write(armv8pmu_pmcr_read() |
+ OPTEE_BENCH_ARMV8_PMCR_E);
+#else
+ /* Enable EL0 access to PMU counters */
+ asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r"(1));
+ /* Enable all PMU counters */
+ asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"
+ (OPTEE_BENCH_DIVIDER_OPTS));
+ /* Disable counter overflow interrupts */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(OPTEE_BENCH_DEF_OVER));
+#endif
+}
+
+static void optee_pmu_disable(void *data)
+{
+#ifdef __aarch64__
+ /* Disable EL0 access */
+ asm volatile("msr pmuserenr_el0, %0" :: "r"((u64)0));
+ /* Disable PMU counters */
+ armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ~OPTEE_BENCH_ARMV8_PMCR_E);
+#else
+ /* Disable all PMU counters */
+ asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(0));
+ /* Enable counter overflow interrupts */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" :: "r"(OPTEE_BENCH_DEF_OVER));
+ /* Disable EL0 access to PMU counters. */
+ asm volatile("mcr p15, 0, %0, c9, c14, 0" :: "r"(0));
+#endif
+}
+
+void optee_bm_enable(void)
+{
+ on_each_cpu(optee_pmu_setup, NULL, 1);
+}
+
+void optee_bm_disable(void)
+{
+ on_each_cpu(optee_pmu_disable, NULL, 1);
+}
+
+void optee_bm_timestamp(void)
+{
+ struct optee_ts_cpu_buf *cpu_buf;
+ struct optee_time_st ts_data;
+ uint64_t ts_i;
+ void *ret_addr;
+ int cur_cpu = 0;
+ int ret;
+
+ down_read(&optee_bench_ts_rwsem);
+
+ if (!optee_bench_ts_global) {
+ up_read(&optee_bench_ts_rwsem);
+ return;
+ }
+
+ cur_cpu = get_cpu();
+
+ if (cur_cpu >= optee_bench_ts_global->cores) {
+ put_cpu();
+ up_read(&optee_bench_ts_rwsem);
+ return;
+ }
+
+ ret_addr = __builtin_return_address(0);
+
+ cpu_buf = &optee_bench_ts_global->cpu_buf[cur_cpu];
+ ts_i = __sync_fetch_and_add(&cpu_buf->head, 1);
+ ts_data.cnt = read_ccounter();
+ ts_data.addr = (uintptr_t)ret_addr;
+ ts_data.src = OPTEE_BENCH_KMOD;
+ cpu_buf->stamps[ts_i & OPTEE_BENCH_MAX_MASK] = ts_data;
+
+ up_read(&optee_bench_ts_rwsem);
+
+ put_cpu();
+}
+#endif /* CONFIG_OPTEE_BENCHMARK */
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
new file mode 100644
index 00000000..0d8605dd
--- /dev/null
+++ b/drivers/tee/optee/call.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/arm-smccc.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include "optee_private.h"
+#include "optee_smc.h"
+#include "optee_bench.h"
+
+struct optee_call_waiter {
+ struct list_head list_node;
+ struct completion c;
+};
+
+static void optee_cq_wait_init(struct optee_call_queue *cq,
+ struct optee_call_waiter *w)
+{
+ /*
+ * We're preparing to make a call to secure world. In case we can't
+ * allocate a thread in secure world we'll end up waiting in
+ * optee_cq_wait_for_completion().
+ *
+ * Normally if there's no contention in secure world the call will
+ * complete and we can cleanup directly with optee_cq_wait_final().
+ */
+ mutex_lock(&cq->mutex);
+
+ /*
+ * We add ourselves to the queue, but we don't wait. This
+ * guarantees that we don't lose a completion if secure world
+ * returns busy and another thread just exited and try to complete
+ * someone.
+ */
+ init_completion(&w->c);
+ list_add_tail(&w->list_node, &cq->waiters);
+
+ mutex_unlock(&cq->mutex);
+}
+
+static void optee_cq_wait_for_completion(struct optee_call_queue *cq,
+ struct optee_call_waiter *w)
+{
+ wait_for_completion(&w->c);
+
+ mutex_lock(&cq->mutex);
+
+ /* Move to end of list to get out of the way for other waiters */
+ list_del(&w->list_node);
+ reinit_completion(&w->c);
+ list_add_tail(&w->list_node, &cq->waiters);
+
+ mutex_unlock(&cq->mutex);
+}
+
+static void optee_cq_complete_one(struct optee_call_queue *cq)
+{
+ struct optee_call_waiter *w;
+
+ list_for_each_entry(w, &cq->waiters, list_node) {
+ if (!completion_done(&w->c)) {
+ complete(&w->c);
+ break;
+ }
+ }
+}
+
+static void optee_cq_wait_final(struct optee_call_queue *cq,
+ struct optee_call_waiter *w)
+{
+ /*
+ * We're done with the call to secure world. The thread in secure
+ * world that was used for this call is now available for some
+ * other task to use.
+ */
+ mutex_lock(&cq->mutex);
+
+ /* Get out of the list */
+ list_del(&w->list_node);
+
+ /* Wake up one eventual waiting task */
+ optee_cq_complete_one(cq);
+
+ /*
+ * If we're completed we've got a completion from another task that
+ * was just done with its call to secure world. Since yet another
+ * thread now is available in secure world wake up another eventual
+ * waiting task.
+ */
+ if (completion_done(&w->c))
+ optee_cq_complete_one(cq);
+
+ mutex_unlock(&cq->mutex);
+}
+
+/* Requires the filpstate mutex to be held */
+static struct optee_session *find_session(struct optee_context_data *ctxdata,
+ u32 session_id)
+{
+ struct optee_session *sess;
+
+ list_for_each_entry(sess, &ctxdata->sess_list, list_node)
+ if (sess->session_id == session_id)
+ return sess;
+
+ return NULL;
+}
+
+/**
+ * optee_do_call_with_arg() - Do an SMC to OP-TEE in secure world
+ * @ctx: calling context
+ * @parg: physical address of message to pass to secure world
+ *
+ * Does and SMC to OP-TEE in secure world and handles eventual resulting
+ * Remote Procedure Calls (RPC) from OP-TEE.
+ *
+ * Returns return code from secure world, 0 is OK
+ */
+u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+{
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_call_waiter w;
+ struct optee_rpc_param param = { };
+ struct optee_call_ctx call_ctx = { };
+ u32 ret;
+
+ param.a0 = OPTEE_SMC_CALL_WITH_ARG;
+ reg_pair_from_64(&param.a1, &param.a2, parg);
+ /* Initialize waiter */
+ optee_cq_wait_init(&optee->call_queue, &w);
+ while (true) {
+ struct arm_smccc_res res;
+
+ optee_bm_timestamp();
+
+ optee->invoke_fn(param.a0, param.a1, param.a2, param.a3,
+ param.a4, param.a5, param.a6, param.a7,
+ &res);
+
+ optee_bm_timestamp();
+
+ if (res.a0 == OPTEE_SMC_RETURN_ETHREAD_LIMIT) {
+ /*
+ * Out of threads in secure world, wait for a thread
+ * become available.
+ */
+ optee_cq_wait_for_completion(&optee->call_queue, &w);
+ } else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
+ param.a0 = res.a0;
+ param.a1 = res.a1;
+ param.a2 = res.a2;
+ param.a3 = res.a3;
+ optee_handle_rpc(ctx, &param, &call_ctx);
+ } else {
+ ret = res.a0;
+ break;
+ }
+ }
+
+ optee_rpc_finalize_call(&call_ctx);
+ /*
+ * We're done with our thread in secure world, if there's any
+ * thread waiters wake up one.
+ */
+ optee_cq_wait_final(&optee->call_queue, &w);
+
+ return ret;
+}
+
+static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+ struct optee_msg_arg **msg_arg,
+ phys_addr_t *msg_parg)
+{
+ int rc;
+ struct tee_shm *shm;
+ struct optee_msg_arg *ma;
+
+ shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
+ TEE_SHM_MAPPED);
+ if (IS_ERR(shm))
+ return shm;
+
+ ma = tee_shm_get_va(shm, 0);
+ if (IS_ERR(ma)) {
+ rc = PTR_ERR(ma);
+ goto out;
+ }
+
+ rc = tee_shm_get_pa(shm, 0, msg_parg);
+ if (rc)
+ goto out;
+
+ memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
+ ma->num_params = num_params;
+ *msg_arg = ma;
+out:
+ if (rc) {
+ tee_shm_free(shm);
+ return ERR_PTR(rc);
+ }
+
+ return shm;
+}
+
+int optee_open_session(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param)
+{
+ struct optee_context_data *ctxdata = ctx->data;
+ int rc;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+ phys_addr_t msg_parg;
+ struct optee_session *sess = NULL;
+
+ /* +2 for the meta parameters added below */
+ shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
+ msg_arg->cancel_id = arg->cancel_id;
+
+ /*
+ * Initialize and add the meta parameters needed when opening a
+ * session.
+ */
+ msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+ OPTEE_MSG_ATTR_META;
+ msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+ OPTEE_MSG_ATTR_META;
+ memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
+ memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
+ msg_arg->params[1].u.value.c = arg->clnt_login;
+
+ rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
+ if (rc)
+ goto out;
+
+ sess = kzalloc(sizeof(*sess), GFP_KERNEL);
+ if (!sess) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ if (optee_do_call_with_arg(ctx, msg_parg)) {
+ msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ }
+
+ if (msg_arg->ret == TEEC_SUCCESS) {
+ /* A new session has been created, add it to the list. */
+ sess->session_id = msg_arg->session;
+ mutex_lock(&ctxdata->mutex);
+ list_add(&sess->list_node, &ctxdata->sess_list);
+ mutex_unlock(&ctxdata->mutex);
+ } else {
+ kfree(sess);
+ }
+
+ if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
+ arg->ret = TEEC_ERROR_COMMUNICATION;
+ arg->ret_origin = TEEC_ORIGIN_COMMS;
+ /* Close session again to avoid leakage */
+ optee_close_session(ctx, msg_arg->session);
+ } else {
+ arg->session = msg_arg->session;
+ arg->ret = msg_arg->ret;
+ arg->ret_origin = msg_arg->ret_origin;
+ }
+out:
+ tee_shm_free(shm);
+
+ return rc;
+}
+
+int optee_close_session(struct tee_context *ctx, u32 session)
+{
+ struct optee_context_data *ctxdata = ctx->data;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+ phys_addr_t msg_parg;
+ struct optee_session *sess;
+
+ /* Check that the session is valid and remove it from the list */
+ mutex_lock(&ctxdata->mutex);
+ sess = find_session(ctxdata, session);
+ if (sess)
+ list_del(&sess->list_node);
+ mutex_unlock(&ctxdata->mutex);
+ if (!sess)
+ return -EINVAL;
+ kfree(sess);
+
+ shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+ msg_arg->session = session;
+ optee_do_call_with_arg(ctx, msg_parg);
+
+ tee_shm_free(shm);
+ return 0;
+}
+
+int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ struct tee_param *param)
+{
+ struct optee_context_data *ctxdata = ctx->data;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+ phys_addr_t msg_parg;
+ struct optee_session *sess;
+ int rc;
+
+ /* Check that the session is valid */
+ mutex_lock(&ctxdata->mutex);
+ sess = find_session(ctxdata, arg->session);
+ mutex_unlock(&ctxdata->mutex);
+ if (!sess)
+ return -EINVAL;
+
+ shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+ msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
+ msg_arg->func = arg->func;
+ msg_arg->session = arg->session;
+ msg_arg->cancel_id = arg->cancel_id;
+
+ rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
+ if (rc)
+ goto out;
+
+ if (optee_do_call_with_arg(ctx, msg_parg)) {
+ msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ }
+
+ if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
+ msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ }
+
+ arg->ret = msg_arg->ret;
+ arg->ret_origin = msg_arg->ret_origin;
+out:
+ tee_shm_free(shm);
+ return rc;
+}
+
+int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
+{
+ struct optee_context_data *ctxdata = ctx->data;
+ struct tee_shm *shm;
+ struct optee_msg_arg *msg_arg;
+ phys_addr_t msg_parg;
+ struct optee_session *sess;
+
+ /* Check that the session is valid */
+ mutex_lock(&ctxdata->mutex);
+ sess = find_session(ctxdata, session);
+ mutex_unlock(&ctxdata->mutex);
+ if (!sess)
+ return -EINVAL;
+
+ shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
+ msg_arg->session = session;
+ msg_arg->cancel_id = cancel_id;
+ optee_do_call_with_arg(ctx, msg_parg);
+
+ tee_shm_free(shm);
+ return 0;
+}
+
+/**
+ * optee_enable_shm_cache() - Enables caching of some shared memory allocation
+ * in OP-TEE
+ * @optee: main service struct
+ */
+void optee_enable_shm_cache(struct optee *optee)
+{
+ struct optee_call_waiter w;
+
+ /* We need to retry until secure world isn't busy. */
+ optee_cq_wait_init(&optee->call_queue, &w);
+ while (true) {
+ struct arm_smccc_res res;
+
+ optee->invoke_fn(OPTEE_SMC_ENABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
+ 0, &res);
+ if (res.a0 == OPTEE_SMC_RETURN_OK)
+ break;
+ optee_cq_wait_for_completion(&optee->call_queue, &w);
+ }
+ optee_cq_wait_final(&optee->call_queue, &w);
+}
+
+/**
+ * optee_disable_shm_cache() - Disables caching of some shared memory allocation
+ * in OP-TEE
+ * @optee: main service struct
+ */
+void optee_disable_shm_cache(struct optee *optee)
+{
+ struct optee_call_waiter w;
+
+ /* We need to retry until secure world isn't busy. */
+ optee_cq_wait_init(&optee->call_queue, &w);
+ while (true) {
+ union {
+ struct arm_smccc_res smccc;
+ struct optee_smc_disable_shm_cache_result result;
+ } res;
+
+ optee->invoke_fn(OPTEE_SMC_DISABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
+ 0, &res.smccc);
+ if (res.result.status == OPTEE_SMC_RETURN_ENOTAVAIL)
+ break; /* All shm's freed */
+ if (res.result.status == OPTEE_SMC_RETURN_OK) {
+ struct tee_shm *shm;
+
+ shm = reg_pair_to_ptr(res.result.shm_upper32,
+ res.result.shm_lower32);
+ tee_shm_free(shm);
+ } else {
+ optee_cq_wait_for_completion(&optee->call_queue, &w);
+ }
+ }
+ optee_cq_wait_final(&optee->call_queue, &w);
+}
+
+#define PAGELIST_ENTRIES_PER_PAGE \
+ ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
+
+/**
+ * optee_fill_pages_list() - write list of user pages to given shared
+ * buffer.
+ *
+ * @dst: page-aligned buffer where list of pages will be stored
+ * @pages: array of pages that represents shared buffer
+ * @num_pages: number of entries in @pages
+ * @page_offset: offset of user buffer from page start
+ *
+ * @dst should be big enough to hold list of user page addresses and
+ * links to the next pages of buffer
+ */
+void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
+ size_t page_offset)
+{
+ int n = 0;
+ phys_addr_t optee_page;
+ /*
+ * Refer to OPTEE_MSG_ATTR_NONCONTIG description in optee_msg.h
+ * for details.
+ */
+ struct {
+ u64 pages_list[PAGELIST_ENTRIES_PER_PAGE];
+ u64 next_page_data;
+ } *pages_data;
+
+ /*
+ * Currently OP-TEE uses 4k page size and it does not looks
+ * like this will change in the future. On other hand, there are
+ * no know ARM architectures with page size < 4k.
+ * Thus the next built assert looks redundant. But the following
+ * code heavily relies on this assumption, so it is better be
+ * safe than sorry.
+ */
+ BUILD_BUG_ON(PAGE_SIZE < OPTEE_MSG_NONCONTIG_PAGE_SIZE);
+
+ pages_data = (void *)dst;
+ /*
+ * If linux page is bigger than 4k, and user buffer offset is
+ * larger than 4k/8k/12k/etc this will skip first 4k pages,
+ * because they bear no value data for OP-TEE.
+ */
+ optee_page = page_to_phys(*pages) +
+ round_down(page_offset, OPTEE_MSG_NONCONTIG_PAGE_SIZE);
+
+ while (true) {
+ pages_data->pages_list[n++] = optee_page;
+
+ if (n == PAGELIST_ENTRIES_PER_PAGE) {
+ pages_data->next_page_data =
+ virt_to_phys(pages_data + 1);
+ pages_data++;
+ n = 0;
+ }
+
+ optee_page += OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+ if (!(optee_page & ~PAGE_MASK)) {
+ if (!--num_pages)
+ break;
+ pages++;
+ optee_page = page_to_phys(*pages);
+ }
+ }
+}
+
+/*
+ * The final entry in each pagelist page is a pointer to the next
+ * pagelist page.
+ */
+static size_t get_pages_list_size(size_t num_entries)
+{
+ int pages = DIV_ROUND_UP(num_entries, PAGELIST_ENTRIES_PER_PAGE);
+
+ return pages * OPTEE_MSG_NONCONTIG_PAGE_SIZE;
+}
+
+u64 *optee_allocate_pages_list(size_t num_entries)
+{
+ return alloc_pages_exact(get_pages_list_size(num_entries), GFP_KERNEL);
+}
+
+void optee_free_pages_list(void *list, size_t num_entries)
+{
+ free_pages_exact(list, get_pages_list_size(num_entries));
+}
+
+static bool is_normal_memory(pgprot_t p)
+{
+#if defined(CONFIG_ARM)
+ return (pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC;
+#elif defined(CONFIG_ARM64)
+ return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL);
+#else
+#error "Unuspported architecture"
+#endif
+}
+
+static int __check_mem_type(struct vm_area_struct *vma, unsigned long end)
+{
+ while (vma && is_normal_memory(vma->vm_page_prot)) {
+ if (vma->vm_end >= end)
+ return 0;
+ vma = vma->vm_next;
+ }
+
+ return -EINVAL;
+}
+
+static int check_mem_type(unsigned long start, size_t num_pages)
+{
+ struct mm_struct *mm = current->mm;
+ int rc;
+
+ down_read(&mm->mmap_sem);
+ rc = __check_mem_type(find_vma(mm, start),
+ start + num_pages * PAGE_SIZE);
+ up_read(&mm->mmap_sem);
+
+ return rc;
+}
+
+int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ struct page **pages, size_t num_pages,
+ unsigned long start)
+{
+ struct tee_shm *shm_arg = NULL;
+ struct optee_msg_arg *msg_arg;
+ u64 *pages_list;
+ phys_addr_t msg_parg;
+ int rc;
+
+ if (!num_pages)
+ return -EINVAL;
+
+ rc = check_mem_type(start, num_pages);
+ if (rc)
+ return rc;
+
+ pages_list = optee_allocate_pages_list(num_pages);
+ if (!pages_list)
+ return -ENOMEM;
+
+ shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
+ if (IS_ERR(shm_arg)) {
+ rc = PTR_ERR(shm_arg);
+ goto out;
+ }
+
+ optee_fill_pages_list(pages_list, pages, num_pages,
+ tee_shm_get_page_offset(shm));
+
+ msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM;
+ msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
+ OPTEE_MSG_ATTR_NONCONTIG;
+ msg_arg->params->u.tmem.shm_ref = (unsigned long)shm;
+ msg_arg->params->u.tmem.size = tee_shm_get_size(shm);
+ /*
+ * In the least bits of msg_arg->params->u.tmem.buf_ptr we
+ * store buffer offset from 4k page, as described in OP-TEE ABI.
+ */
+ msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
+ (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
+
+ if (optee_do_call_with_arg(ctx, msg_parg) ||
+ msg_arg->ret != TEEC_SUCCESS)
+ rc = -EINVAL;
+
+ tee_shm_free(shm_arg);
+out:
+ optee_free_pages_list(pages_list, num_pages);
+ return rc;
+}
+
+int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
+{
+ struct tee_shm *shm_arg;
+ struct optee_msg_arg *msg_arg;
+ phys_addr_t msg_parg;
+ int rc = 0;
+
+ shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
+ if (IS_ERR(shm_arg))
+ return PTR_ERR(shm_arg);
+
+ msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
+
+ msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
+
+ if (optee_do_call_with_arg(ctx, msg_parg) ||
+ msg_arg->ret != TEEC_SUCCESS)
+ rc = -EINVAL;
+ tee_shm_free(shm_arg);
+ return rc;
+}
+
+int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
+ struct page **pages, size_t num_pages,
+ unsigned long start)
+{
+ /*
+ * We don't want to register supplicant memory in OP-TEE.
+ * Instead information about it will be passed in RPC code.
+ */
+ return check_mem_type(start, num_pages);
+}
+
+int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
+{
+ return 0;
+}
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
new file mode 100644
index 00000000..be6099ae
--- /dev/null
+++ b/drivers/tee/optee/core.c
@@ -0,0 +1,745 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/arm-smccc.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tee_drv.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include "optee_bench.h"
+#include "optee_private.h"
+#include "optee_smc.h"
+#include "shm_pool.h"
+
+#define DRIVER_NAME "optee"
+
+#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
+
+/**
+ * optee_from_msg_param() - convert from OPTEE_MSG parameters to
+ * struct tee_param
+ * @params: subsystem internal parameter representation
+ * @num_params: number of elements in the parameter arrays
+ * @msg_params: OPTEE_MSG parameters
+ * Returns 0 on success or <0 on failure
+ */
+int optee_from_msg_param(struct tee_param *params, size_t num_params,
+ const struct optee_msg_param *msg_params)
+{
+ int rc;
+ size_t n;
+ struct tee_shm *shm;
+ phys_addr_t pa;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_param *p = params + n;
+ const struct optee_msg_param *mp = msg_params + n;
+ u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
+
+ switch (attr) {
+ case OPTEE_MSG_ATTR_TYPE_NONE:
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
+ memset(&p->u, 0, sizeof(p->u));
+ break;
+ case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
+ attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+ p->u.value.a = mp->u.value.a;
+ p->u.value.b = mp->u.value.b;
+ p->u.value.c = mp->u.value.c;
+ break;
+ case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+ attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
+ p->u.memref.size = mp->u.tmem.size;
+ shm = (struct tee_shm *)(unsigned long)
+ mp->u.tmem.shm_ref;
+ if (!shm) {
+ p->u.memref.shm_offs = 0;
+ p->u.memref.shm = NULL;
+ break;
+ }
+ rc = tee_shm_get_pa(shm, 0, &pa);
+ if (rc)
+ return rc;
+ p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
+ p->u.memref.shm = shm;
+
+ /* Check that the memref is covered by the shm object */
+ if (p->u.memref.size) {
+ size_t o = p->u.memref.shm_offs +
+ p->u.memref.size - 1;
+
+ rc = tee_shm_get_pa(shm, o, NULL);
+ if (rc)
+ return rc;
+ }
+ break;
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
+ case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+ p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+ attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ p->u.memref.size = mp->u.rmem.size;
+ shm = (struct tee_shm *)(unsigned long)
+ mp->u.rmem.shm_ref;
+
+ if (!shm) {
+ p->u.memref.shm_offs = 0;
+ p->u.memref.shm = NULL;
+ break;
+ }
+ p->u.memref.shm_offs = mp->u.rmem.offs;
+ p->u.memref.shm = shm;
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
+ const struct tee_param *p)
+{
+ int rc;
+ phys_addr_t pa;
+
+ mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+
+ mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
+ mp->u.tmem.size = p->u.memref.size;
+
+ if (!p->u.memref.shm) {
+ mp->u.tmem.buf_ptr = 0;
+ return 0;
+ }
+
+ rc = tee_shm_get_pa(p->u.memref.shm, p->u.memref.shm_offs, &pa);
+ if (rc)
+ return rc;
+
+ mp->u.tmem.buf_ptr = pa;
+ mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
+ OPTEE_MSG_ATTR_CACHE_SHIFT;
+
+ return 0;
+}
+
+static int to_msg_param_reg_mem(struct optee_msg_param *mp,
+ const struct tee_param *p)
+{
+ mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr -
+ TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+
+ mp->u.rmem.shm_ref = (unsigned long)p->u.memref.shm;
+ mp->u.rmem.size = p->u.memref.size;
+ mp->u.rmem.offs = p->u.memref.shm_offs;
+ return 0;
+}
+
+/**
+ * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
+ * @msg_params: OPTEE_MSG parameters
+ * @num_params: number of elements in the parameter arrays
+ * @params: subsystem itnernal parameter representation
+ * Returns 0 on success or <0 on failure
+ */
+int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+ const struct tee_param *params)
+{
+ int rc;
+ size_t n;
+
+ for (n = 0; n < num_params; n++) {
+ const struct tee_param *p = params + n;
+ struct optee_msg_param *mp = msg_params + n;
+
+ switch (p->attr) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+ mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
+ memset(&mp->u, 0, sizeof(mp->u));
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+ TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+ mp->u.value.a = p->u.value.a;
+ mp->u.value.b = p->u.value.b;
+ mp->u.value.c = p->u.value.c;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ if (tee_shm_is_registered(p->u.memref.shm))
+ rc = to_msg_param_reg_mem(mp, p);
+ else
+ rc = to_msg_param_tmp_mem(mp, p);
+ if (rc)
+ return rc;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static void optee_get_version(struct tee_device *teedev,
+ struct tee_ioctl_version_data *vers)
+{
+ struct tee_ioctl_version_data v = {
+ .impl_id = TEE_IMPL_ID_OPTEE,
+ .impl_caps = TEE_OPTEE_CAP_TZ,
+ .gen_caps = TEE_GEN_CAP_GP,
+ };
+ struct optee *optee = tee_get_drvdata(teedev);
+
+ if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
+ v.gen_caps |= TEE_GEN_CAP_REG_MEM;
+ *vers = v;
+}
+
+static int optee_open(struct tee_context *ctx)
+{
+ struct optee_context_data *ctxdata;
+ struct tee_device *teedev = ctx->teedev;
+ struct optee *optee = tee_get_drvdata(teedev);
+
+ ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
+ if (!ctxdata)
+ return -ENOMEM;
+
+ if (teedev == optee->supp_teedev) {
+ bool busy = true;
+
+ mutex_lock(&optee->supp.mutex);
+ if (!optee->supp.ctx) {
+ busy = false;
+ optee->supp.ctx = ctx;
+ }
+ mutex_unlock(&optee->supp.mutex);
+ if (busy) {
+ kfree(ctxdata);
+ return -EBUSY;
+ }
+ }
+
+ mutex_init(&ctxdata->mutex);
+ INIT_LIST_HEAD(&ctxdata->sess_list);
+
+ ctx->data = ctxdata;
+ return 0;
+}
+
+static void optee_release(struct tee_context *ctx)
+{
+ struct optee_context_data *ctxdata = ctx->data;
+ struct tee_device *teedev = ctx->teedev;
+ struct optee *optee = tee_get_drvdata(teedev);
+ struct tee_shm *shm;
+ struct optee_msg_arg *arg = NULL;
+ phys_addr_t parg;
+ struct optee_session *sess;
+ struct optee_session *sess_tmp;
+
+ if (!ctxdata)
+ return;
+
+ shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
+ if (!IS_ERR(shm)) {
+ arg = tee_shm_get_va(shm, 0);
+ /*
+ * If va2pa fails for some reason, we can't call into
+ * secure world, only free the memory. Secure OS will leak
+ * sessions and finally refuse more sessions, but we will
+ * at least let normal world reclaim its memory.
+ */
+ if (!IS_ERR(arg))
+ if (tee_shm_va2pa(shm, arg, &parg))
+ arg = NULL; /* prevent usage of parg below */
+ }
+
+ list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
+ list_node) {
+ list_del(&sess->list_node);
+ if (!IS_ERR_OR_NULL(arg)) {
+ memset(arg, 0, sizeof(*arg));
+ arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+ arg->session = sess->session_id;
+ optee_do_call_with_arg(ctx, parg);
+ }
+ kfree(sess);
+ }
+ kfree(ctxdata);
+
+ if (!IS_ERR(shm))
+ tee_shm_free(shm);
+
+ ctx->data = NULL;
+
+ if (teedev == optee->supp_teedev)
+ optee_supp_release(&optee->supp);
+}
+
+static const struct tee_driver_ops optee_ops = {
+ .get_version = optee_get_version,
+ .open = optee_open,
+ .release = optee_release,
+ .open_session = optee_open_session,
+ .close_session = optee_close_session,
+ .invoke_func = optee_invoke_func,
+ .cancel_req = optee_cancel_req,
+ .shm_register = optee_shm_register,
+ .shm_unregister = optee_shm_unregister,
+};
+
+static const struct tee_desc optee_desc = {
+ .name = DRIVER_NAME "-clnt",
+ .ops = &optee_ops,
+ .owner = THIS_MODULE,
+};
+
+static const struct tee_driver_ops optee_supp_ops = {
+ .get_version = optee_get_version,
+ .open = optee_open,
+ .release = optee_release,
+ .supp_recv = optee_supp_recv,
+ .supp_send = optee_supp_send,
+ .shm_register = optee_shm_register_supp,
+ .shm_unregister = optee_shm_unregister_supp,
+};
+
+static const struct tee_desc optee_supp_desc = {
+ .name = DRIVER_NAME "-supp",
+ .ops = &optee_supp_ops,
+ .owner = THIS_MODULE,
+ .flags = TEE_DESC_PRIVILEGED,
+};
+
+static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
+{
+ struct arm_smccc_res res;
+
+ invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+ if (res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+ res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3)
+ return true;
+ return false;
+}
+
+static void optee_msg_get_os_revision(optee_invoke_fn *invoke_fn)
+{
+ union {
+ struct arm_smccc_res smccc;
+ struct optee_smc_call_get_os_revision_result result;
+ } res = {
+ .result = {
+ .build_id = 0
+ }
+ };
+
+ invoke_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0,
+ &res.smccc);
+
+ if (res.result.build_id)
+ pr_info("revision %lu.%lu (%08lx)", res.result.major,
+ res.result.minor, res.result.build_id);
+ else
+ pr_info("revision %lu.%lu", res.result.major, res.result.minor);
+}
+
+static bool optee_msg_api_revision_is_compatible(optee_invoke_fn *invoke_fn)
+{
+ union {
+ struct arm_smccc_res smccc;
+ struct optee_smc_calls_revision_result result;
+ } res;
+
+ invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+ if (res.result.major == OPTEE_MSG_REVISION_MAJOR &&
+ (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR)
+ return true;
+ return false;
+}
+
+static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
+ u32 *sec_caps)
+{
+ union {
+ struct arm_smccc_res smccc;
+ struct optee_smc_exchange_capabilities_result result;
+ } res;
+ u32 a1 = 0;
+
+ /*
+ * TODO This isn't enough to tell if it's UP system (from kernel
+ * point of view) or not, is_smp() returns the the information
+ * needed, but can't be called directly from here.
+ */
+ if (!IS_ENABLED(CONFIG_SMP) || nr_cpu_ids == 1)
+ a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR;
+
+ invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, a1, 0, 0, 0, 0, 0, 0,
+ &res.smccc);
+
+ if (res.result.status != OPTEE_SMC_RETURN_OK)
+ return false;
+
+ *sec_caps = res.result.capabilities;
+ return true;
+}
+
+static struct tee_shm_pool *
+optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm,
+ u32 sec_caps)
+{
+ union {
+ struct arm_smccc_res smccc;
+ struct optee_smc_get_shm_config_result result;
+ } res;
+ unsigned long vaddr;
+ phys_addr_t paddr;
+ size_t size;
+ phys_addr_t begin;
+ phys_addr_t end;
+ void *va;
+ struct tee_shm_pool_mgr *priv_mgr;
+ struct tee_shm_pool_mgr *dmabuf_mgr;
+ void *rc;
+
+ invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+ if (res.result.status != OPTEE_SMC_RETURN_OK) {
+ pr_info("shm service not available\n");
+ return ERR_PTR(-ENOENT);
+ }
+
+ if (res.result.settings != OPTEE_SMC_SHM_CACHED) {
+ pr_err("only normal cached shared memory supported\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ begin = roundup(res.result.start, PAGE_SIZE);
+ end = rounddown(res.result.start + res.result.size, PAGE_SIZE);
+ paddr = begin;
+ size = end - begin;
+
+ if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) {
+ pr_err("too small shared memory area\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ va = memremap(paddr, size, MEMREMAP_WB);
+ if (!va) {
+ pr_err("shared memory ioremap failed\n");
+ return ERR_PTR(-EINVAL);
+ }
+ vaddr = (unsigned long)va;
+
+ /*
+ * If OP-TEE can work with unregistered SHM, we will use own pool
+ * for private shm
+ */
+ if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) {
+ rc = optee_shm_pool_alloc_pages();
+ if (IS_ERR(rc))
+ goto err_memunmap;
+ priv_mgr = rc;
+ } else {
+ const size_t sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
+
+ rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz,
+ 3 /* 8 bytes aligned */);
+ if (IS_ERR(rc))
+ goto err_memunmap;
+ priv_mgr = rc;
+
+ vaddr += sz;
+ paddr += sz;
+ size -= sz;
+ }
+
+ rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, size, PAGE_SHIFT);
+ if (IS_ERR(rc))
+ goto err_free_priv_mgr;
+ dmabuf_mgr = rc;
+
+ rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
+ if (IS_ERR(rc))
+ goto err_free_dmabuf_mgr;
+
+ *memremaped_shm = va;
+
+ return rc;
+
+err_free_dmabuf_mgr:
+ tee_shm_pool_mgr_destroy(dmabuf_mgr);
+err_free_priv_mgr:
+ tee_shm_pool_mgr_destroy(priv_mgr);
+err_memunmap:
+ memunmap(va);
+ return rc;
+}
+
+/* Simple wrapper functions to be able to use a function pointer */
+static void optee_smccc_smc(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ unsigned long a6, unsigned long a7,
+ struct arm_smccc_res *res)
+{
+ arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ unsigned long a6, unsigned long a7,
+ struct arm_smccc_res *res)
+{
+ arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+static optee_invoke_fn *get_invoke_func(struct device_node *np)
+{
+ const char *method;
+
+ pr_info("probing for conduit method from DT.\n");
+
+ if (of_property_read_string(np, "method", &method)) {
+ pr_warn("missing \"method\" property\n");
+ return ERR_PTR(-ENXIO);
+ }
+
+ if (!strcmp("hvc", method))
+ return optee_smccc_hvc;
+ else if (!strcmp("smc", method))
+ return optee_smccc_smc;
+
+ pr_warn("invalid \"method\" property: %s\n", method);
+ return ERR_PTR(-EINVAL);
+}
+
+static struct optee *optee_probe(struct device_node *np)
+{
+ optee_invoke_fn *invoke_fn;
+ struct tee_shm_pool *pool;
+ struct optee *optee = NULL;
+ void *memremaped_shm = NULL;
+ struct tee_device *teedev;
+ u32 sec_caps;
+ int rc;
+
+ if (np)
+ invoke_fn = get_invoke_func(np);
+ else
+ invoke_fn = optee_smccc_smc;
+ if (IS_ERR(invoke_fn))
+ return (void *)invoke_fn;
+
+ if (!optee_msg_api_uid_is_optee_api(invoke_fn)) {
+ pr_warn("api uid mismatch\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ optee_msg_get_os_revision(invoke_fn);
+
+ if (!optee_msg_api_revision_is_compatible(invoke_fn)) {
+ pr_warn("api revision mismatch\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) {
+ pr_warn("capabilities mismatch\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ /*
+ * We have no other option for shared memory, if secure world
+ * doesn't have any reserved memory we can use we can't continue.
+ */
+ if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
+ return ERR_PTR(-EINVAL);
+
+ pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm, sec_caps);
+ if (IS_ERR(pool))
+ return (void *)pool;
+
+ optee = kzalloc(sizeof(*optee), GFP_KERNEL);
+ if (!optee) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ optee->invoke_fn = invoke_fn;
+ optee->sec_caps = sec_caps;
+
+ teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
+ if (IS_ERR(teedev)) {
+ rc = PTR_ERR(teedev);
+ goto err;
+ }
+ optee->teedev = teedev;
+
+ teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
+ if (IS_ERR(teedev)) {
+ rc = PTR_ERR(teedev);
+ goto err;
+ }
+ optee->supp_teedev = teedev;
+
+ rc = tee_device_register(optee->teedev);
+ if (rc)
+ goto err;
+
+ rc = tee_device_register(optee->supp_teedev);
+ if (rc)
+ goto err;
+
+ mutex_init(&optee->call_queue.mutex);
+ INIT_LIST_HEAD(&optee->call_queue.waiters);
+ optee_wait_queue_init(&optee->wait_queue);
+ optee_supp_init(&optee->supp);
+ optee->memremaped_shm = memremaped_shm;
+ optee->pool = pool;
+
+ optee_enable_shm_cache(optee);
+
+ if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
+ pr_info("dynamic shared memory is enabled\n");
+
+ pr_info("initialized driver\n");
+ return optee;
+err:
+ if (optee) {
+ /*
+ * tee_device_unregister() is safe to call even if the
+ * devices hasn't been registered with
+ * tee_device_register() yet.
+ */
+ tee_device_unregister(optee->supp_teedev);
+ tee_device_unregister(optee->teedev);
+ kfree(optee);
+ }
+ if (pool)
+ tee_shm_pool_free(pool);
+ if (memremaped_shm)
+ memunmap(memremaped_shm);
+ return ERR_PTR(rc);
+}
+
+static void optee_remove(struct optee *optee)
+{
+ /*
+ * Ask OP-TEE to free all cached shared memory objects to decrease
+ * reference counters and also avoid wild pointers in secure world
+ * into the old shared memory range.
+ */
+ optee_disable_shm_cache(optee);
+
+ /*
+ * The two devices has to be unregistered before we can free the
+ * other resources.
+ */
+ tee_device_unregister(optee->supp_teedev);
+ tee_device_unregister(optee->teedev);
+
+ tee_shm_pool_free(optee->pool);
+ if (optee->memremaped_shm)
+ memunmap(optee->memremaped_shm);
+ optee_wait_queue_exit(&optee->wait_queue);
+ optee_supp_uninit(&optee->supp);
+ mutex_destroy(&optee->call_queue.mutex);
+
+ kfree(optee);
+}
+
+#ifdef CONFIG_USE_OF
+static const struct of_device_id optee_match[] = {
+ { .compatible = "linaro,optee-tz" },
+ {},
+};
+#endif
+
+static struct optee *optee_svc;
+
+static int __init optee_driver_init(void)
+{
+ struct optee *optee;
+#ifdef CONFIG_USE_OF
+ struct device_node *fw_np;
+ struct device_node *np;
+
+ /* Node is supposed to be below /firmware */
+ fw_np = of_find_node_by_name(NULL, "firmware");
+ if (!fw_np)
+ return -ENODEV;
+
+ np = of_find_matching_node(fw_np, optee_match);
+ if (!np || !of_device_is_available(np))
+ return -ENODEV;
+
+ optee = optee_probe(np);
+ of_node_put(np);
+#else
+ optee = optee_probe(NULL);
+#endif
+
+ if (IS_ERR(optee))
+ return PTR_ERR(optee);
+
+ optee_svc = optee;
+
+ optee_bm_enable();
+
+ return 0;
+}
+module_init(optee_driver_init);
+
+static void __exit optee_driver_exit(void)
+{
+ struct optee *optee = optee_svc;
+
+ optee_svc = NULL;
+ if (optee)
+ optee_remove(optee);
+
+ optee_bm_disable();
+}
+module_exit(optee_driver_exit);
+
+MODULE_AUTHOR("Linaro");
+MODULE_DESCRIPTION("OP-TEE driver");
+MODULE_SUPPORTED_DEVICE("");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tee/optee/optee_bench.h b/drivers/tee/optee/optee_bench.h
new file mode 100644
index 00000000..985e6a01
--- /dev/null
+++ b/drivers/tee/optee/optee_bench.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _OPTEE_BENCH_H
+#define _OPTEE_BENCH_H
+
+#include <linux/rwsem.h>
+
+/*
+ * Cycle count divider is enabled (in PMCR),
+ * CCNT value is incremented every 64th clock cycle
+ */
+#define OPTEE_BENCH_DIVIDER 64
+
+/* max amount of timestamps */
+#define OPTEE_BENCH_MAX_STAMPS 32
+#define OPTEE_BENCH_MAX_MASK (OPTEE_BENCH_MAX_STAMPS - 1)
+
+/* OP-TEE susbsystems ids */
+#define OPTEE_BENCH_KMOD 0x20000000
+
+#define OPTEE_MSG_RPC_CMD_BENCH_REG_NEW 0
+#define OPTEE_MSG_RPC_CMD_BENCH_REG_DEL 1
+
+/* storing timestamp */
+struct optee_time_st {
+ uint64_t cnt; /* stores value from CNTPCT register */
+ uint64_t addr; /* stores value from program counter register */
+ uint64_t src; /* OP-TEE subsystem id */
+};
+
+/* per-cpu circular buffer for timestamps */
+struct optee_ts_cpu_buf {
+ uint64_t head;
+ uint64_t tail;
+ struct optee_time_st stamps[OPTEE_BENCH_MAX_STAMPS];
+};
+
+/* memory layout for shared memory, where timestamps will be stored */
+struct optee_ts_global {
+ uint64_t cores;
+ struct optee_ts_cpu_buf cpu_buf[];
+};
+
+extern struct optee_ts_global *optee_bench_ts_global;
+extern struct rw_semaphore optee_bench_ts_rwsem;
+
+#ifdef CONFIG_OPTEE_BENCHMARK
+void optee_bm_enable(void);
+void optee_bm_disable(void);
+void optee_bm_timestamp(void);
+#else
+static inline void optee_bm_enable(void) {}
+static inline void optee_bm_disable(void) {}
+static inline void optee_bm_timestamp(void) {}
+#endif /* CONFIG_OPTEE_BENCHMARK */
+#endif /* _OPTEE_BENCH_H */
diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
new file mode 100644
index 00000000..aebcbeba
--- /dev/null
+++ b/drivers/tee/optee/optee_msg.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _OPTEE_MSG_H
+#define _OPTEE_MSG_H
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+/*
+ * This file defines the OP-TEE message protocol used to communicate
+ * with an instance of OP-TEE running in secure world.
+ *
+ * This file is divided into three sections.
+ * 1. Formatting of messages.
+ * 2. Requests from normal world
+ * 3. Requests from secure world, Remote Procedure Call (RPC), handled by
+ * tee-supplicant.
+ */
+
+/*****************************************************************************
+ * Part 1 - formatting of messages
+ *****************************************************************************/
+
+#define OPTEE_MSG_ATTR_TYPE_NONE 0x0
+#define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT 0x1
+#define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT 0x2
+#define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT 0x3
+#define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5
+#define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6
+#define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7
+#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9
+#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa
+#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb
+
+#define OPTEE_MSG_ATTR_TYPE_MASK GENMASK(7, 0)
+
+/*
+ * Meta parameter to be absorbed by the Secure OS and not passed
+ * to the Trusted Application.
+ *
+ * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION.
+ */
+#define OPTEE_MSG_ATTR_META BIT(8)
+
+/*
+ * Pointer to a list of pages used to register user-defined SHM buffer.
+ * Used with OPTEE_MSG_ATTR_TYPE_TMEM_*.
+ * buf_ptr should point to the beginning of the buffer. Buffer will contain
+ * list of page addresses. OP-TEE core can reconstruct contiguous buffer from
+ * that page addresses list. Page addresses are stored as 64 bit values.
+ * Last entry on a page should point to the next page of buffer.
+ * Every entry in buffer should point to a 4k page beginning (12 least
+ * significant bits must be equal to zero).
+ *
+ * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page
+ * offset of the user buffer.
+ *
+ * So, entries should be placed like members of this structure:
+ *
+ * struct page_data {
+ * uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1];
+ * uint64_t next_page_data;
+ * };
+ *
+ * Structure is designed to exactly fit into the page size
+ * OPTEE_MSG_NONCONTIG_PAGE_SIZE which is a standard 4KB page.
+ *
+ * The size of 4KB is chosen because this is the smallest page size for ARM
+ * architectures. If REE uses larger pages, it should divide them to 4KB ones.
+ */
+#define OPTEE_MSG_ATTR_NONCONTIG BIT(9)
+
+/*
+ * Memory attributes for caching passed with temp memrefs. The actual value
+ * used is defined outside the message protocol with the exception of
+ * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already
+ * defined for the memory range should be used. If optee_smc.h is used as
+ * bearer of this protocol OPTEE_SMC_SHM_* is used for values.
+ */
+#define OPTEE_MSG_ATTR_CACHE_SHIFT 16
+#define OPTEE_MSG_ATTR_CACHE_MASK GENMASK(2, 0)
+#define OPTEE_MSG_ATTR_CACHE_PREDEFINED 0
+
+/*
+ * Same values as TEE_LOGIN_* from TEE Internal API
+ */
+#define OPTEE_MSG_LOGIN_PUBLIC 0x00000000
+#define OPTEE_MSG_LOGIN_USER 0x00000001
+#define OPTEE_MSG_LOGIN_GROUP 0x00000002
+#define OPTEE_MSG_LOGIN_APPLICATION 0x00000004
+#define OPTEE_MSG_LOGIN_APPLICATION_USER 0x00000005
+#define OPTEE_MSG_LOGIN_APPLICATION_GROUP 0x00000006
+
+/*
+ * Page size used in non-contiguous buffer entries
+ */
+#define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096
+
+/**
+ * struct optee_msg_param_tmem - temporary memory reference parameter
+ * @buf_ptr: Address of the buffer
+ * @size: Size of the buffer
+ * @shm_ref: Temporary shared memory reference, pointer to a struct tee_shm
+ *
+ * Secure and normal world communicates pointers as physical address
+ * instead of the virtual address. This is because secure and normal world
+ * have completely independent memory mapping. Normal world can even have a
+ * hypervisor which need to translate the guest physical address (AKA IPA
+ * in ARM documentation) to a real physical address before passing the
+ * structure to secure world.
+ */
+struct optee_msg_param_tmem {
+ u64 buf_ptr;
+ u64 size;
+ u64 shm_ref;
+};
+
+/**
+ * struct optee_msg_param_rmem - registered memory reference parameter
+ * @offs: Offset into shared memory reference
+ * @size: Size of the buffer
+ * @shm_ref: Shared memory reference, pointer to a struct tee_shm
+ */
+struct optee_msg_param_rmem {
+ u64 offs;
+ u64 size;
+ u64 shm_ref;
+};
+
+/**
+ * struct optee_msg_param_value - opaque value parameter
+ *
+ * Value parameters are passed unchecked between normal and secure world.
+ */
+struct optee_msg_param_value {
+ u64 a;
+ u64 b;
+ u64 c;
+};
+
+/**
+ * struct optee_msg_param - parameter used together with struct optee_msg_arg
+ * @attr: attributes
+ * @tmem: parameter by temporary memory reference
+ * @rmem: parameter by registered memory reference
+ * @value: parameter by opaque value
+ *
+ * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
+ * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
+ * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
+ * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
+ * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
+ */
+struct optee_msg_param {
+ u64 attr;
+ union {
+ struct optee_msg_param_tmem tmem;
+ struct optee_msg_param_rmem rmem;
+ struct optee_msg_param_value value;
+ } u;
+};
+
+/**
+ * struct optee_msg_arg - call argument
+ * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_*
+ * @func: Trusted Application function, specific to the Trusted Application,
+ * used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND
+ * @session: In parameter for all OPTEE_MSG_CMD_* except
+ * OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead
+ * @cancel_id: Cancellation id, a unique value to identify this request
+ * @ret: return value
+ * @ret_origin: origin of the return value
+ * @num_params: number of parameters supplied to the OS Command
+ * @params: the parameters supplied to the OS Command
+ *
+ * All normal calls to Trusted OS uses this struct. If cmd requires further
+ * information than what these field holds it can be passed as a parameter
+ * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
+ * attrs field). All parameters tagged as meta has to come first.
+ *
+ * Temp memref parameters can be fragmented if supported by the Trusted OS
+ * (when optee_smc.h is bearer of this protocol this is indicated with
+ * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
+ * fragmented then has all but the last fragment the
+ * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
+ * it will still be presented as a single logical memref to the Trusted
+ * Application.
+ */
+struct optee_msg_arg {
+ u32 cmd;
+ u32 func;
+ u32 session;
+ u32 cancel_id;
+ u32 pad;
+ u32 ret;
+ u32 ret_origin;
+ u32 num_params;
+
+ /* num_params tells the actual number of element in params */
+ struct optee_msg_param params[0];
+};
+
+/**
+ * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg
+ *
+ * @num_params: Number of parameters embedded in the struct optee_msg_arg
+ *
+ * Returns the size of the struct optee_msg_arg together with the number
+ * of embedded parameters.
+ */
+#define OPTEE_MSG_GET_ARG_SIZE(num_params) \
+ (sizeof(struct optee_msg_arg) + \
+ sizeof(struct optee_msg_param) * (num_params))
+
+/*****************************************************************************
+ * Part 2 - requests from normal world
+ *****************************************************************************/
+
+/*
+ * Return the following UID if using API specified in this file without
+ * further extensions:
+ * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
+ * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1,
+ * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3.
+ */
+#define OPTEE_MSG_UID_0 0x384fb3e0
+#define OPTEE_MSG_UID_1 0xe7f811e3
+#define OPTEE_MSG_UID_2 0xaf630002
+#define OPTEE_MSG_UID_3 0xa5d5c51b
+#define OPTEE_MSG_FUNCID_CALLS_UID 0xFF01
+
+/*
+ * Returns 2.0 if using API specified in this file without further
+ * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR
+ * and OPTEE_MSG_REVISION_MINOR
+ */
+#define OPTEE_MSG_REVISION_MAJOR 2
+#define OPTEE_MSG_REVISION_MINOR 0
+#define OPTEE_MSG_FUNCID_CALLS_REVISION 0xFF03
+
+/*
+ * Get UUID of Trusted OS.
+ *
+ * Used by non-secure world to figure out which Trusted OS is installed.
+ * Note that returned UUID is the UUID of the Trusted OS, not of the API.
+ *
+ * Returns UUID in 4 32-bit words in the same way as
+ * OPTEE_MSG_FUNCID_CALLS_UID described above.
+ */
+#define OPTEE_MSG_OS_OPTEE_UUID_0 0x486178e0
+#define OPTEE_MSG_OS_OPTEE_UUID_1 0xe7f811e3
+#define OPTEE_MSG_OS_OPTEE_UUID_2 0xbc5e0002
+#define OPTEE_MSG_OS_OPTEE_UUID_3 0xa5d5c51b
+#define OPTEE_MSG_FUNCID_GET_OS_UUID 0x0000
+
+/*
+ * Get revision of Trusted OS.
+ *
+ * Used by non-secure world to figure out which version of the Trusted OS
+ * is installed. Note that the returned revision is the revision of the
+ * Trusted OS, not of the API.
+ *
+ * Returns revision in 2 32-bit words in the same way as
+ * OPTEE_MSG_CALLS_REVISION described above.
+ */
+#define OPTEE_MSG_FUNCID_GET_OS_REVISION 0x0001
+
+/*
+ * Do a secure call with struct optee_msg_arg as argument
+ * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd
+ *
+ * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application.
+ * The first two parameters are tagged as meta, holding two value
+ * parameters to pass the following information:
+ * param[0].u.value.a-b uuid of Trusted Application
+ * param[1].u.value.a-b uuid of Client
+ * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_*
+ *
+ * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened
+ * session to a Trusted Application. struct optee_msg_arg::func is Trusted
+ * Application function, specific to the Trusted Application.
+ *
+ * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to
+ * Trusted Application.
+ *
+ * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command.
+ *
+ * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
+ * information is passed as:
+ * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
+ * [| OPTEE_MSG_ATTR_FRAGMENT]
+ * [in] param[0].u.tmem.buf_ptr physical address (of first fragment)
+ * [in] param[0].u.tmem.size size (of first fragment)
+ * [in] param[0].u.tmem.shm_ref holds shared memory reference
+ * ...
+ * The shared memory can optionally be fragmented, temp memrefs can follow
+ * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
+ *
+ * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
+ * memory reference. The information is passed as:
+ * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
+ * [in] param[0].u.rmem.shm_ref holds shared memory reference
+ * [in] param[0].u.rmem.offs 0
+ * [in] param[0].u.rmem.size 0
+ */
+#define OPTEE_MSG_CMD_OPEN_SESSION 0
+#define OPTEE_MSG_CMD_INVOKE_COMMAND 1
+#define OPTEE_MSG_CMD_CLOSE_SESSION 2
+#define OPTEE_MSG_CMD_CANCEL 3
+#define OPTEE_MSG_CMD_REGISTER_SHM 4
+#define OPTEE_MSG_CMD_UNREGISTER_SHM 5
+#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
+
+/*****************************************************************************
+ * Part 3 - Requests from secure world, RPC
+ *****************************************************************************/
+
+/*
+ * All RPC is done with a struct optee_msg_arg as bearer of information,
+ * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
+ *
+ * RPC communication with tee-supplicant is reversed compared to normal
+ * client communication desribed above. The supplicant receives requests
+ * and sends responses.
+ */
+
+/*
+ * Load a TA into memory, defined in tee-supplicant
+ */
+#define OPTEE_MSG_RPC_CMD_LOAD_TA 0
+
+/*
+ * Reserved
+ */
+#define OPTEE_MSG_RPC_CMD_RPMB 1
+
+/*
+ * File system access, defined in tee-supplicant
+ */
+#define OPTEE_MSG_RPC_CMD_FS 2
+
+/*
+ * Get time
+ *
+ * Returns number of seconds and nano seconds since the Epoch,
+ * 1970-01-01 00:00:00 +0000 (UTC).
+ *
+ * [out] param[0].u.value.a Number of seconds
+ * [out] param[0].u.value.b Number of nano seconds.
+ */
+#define OPTEE_MSG_RPC_CMD_GET_TIME 3
+
+/*
+ * Wait queue primitive, helper for secure world to implement a wait queue.
+ *
+ * If secure world need to wait for a secure world mutex it issues a sleep
+ * request instead of spinning in secure world. Conversely is a wakeup
+ * request issued when a secure world mutex with a thread waiting thread is
+ * unlocked.
+ *
+ * Waiting on a key
+ * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
+ * [in] param[0].u.value.b wait key
+ *
+ * Waking up a key
+ * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
+ * [in] param[0].u.value.b wakeup key
+ */
+#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE 4
+#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
+#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP 1
+
+/*
+ * Suspend execution
+ *
+ * [in] param[0].value .a number of milliseconds to suspend
+ */
+#define OPTEE_MSG_RPC_CMD_SUSPEND 5
+
+/*
+ * Allocate a piece of shared memory
+ *
+ * Shared memory can optionally be fragmented, to support that additional
+ * spare param entries are allocated to make room for eventual fragments.
+ * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
+ * unused. All returned temp memrefs except the last should have the
+ * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
+ *
+ * [in] param[0].u.value.a type of memory one of
+ * OPTEE_MSG_RPC_SHM_TYPE_* below
+ * [in] param[0].u.value.b requested size
+ * [in] param[0].u.value.c required alignment
+ *
+ * [out] param[0].u.tmem.buf_ptr physical address (of first fragment)
+ * [out] param[0].u.tmem.size size (of first fragment)
+ * [out] param[0].u.tmem.shm_ref shared memory reference
+ * ...
+ * [out] param[n].u.tmem.buf_ptr physical address
+ * [out] param[n].u.tmem.size size
+ * [out] param[n].u.tmem.shm_ref shared memory reference (same value
+ * as in param[n-1].u.tmem.shm_ref)
+ */
+#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6
+/* Memory that can be shared with a non-secure user space application */
+#define OPTEE_MSG_RPC_SHM_TYPE_APPL 0
+/* Memory only shared with non-secure kernel */
+#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL 1
+/* Memory shared with non-secure kernel, but exported to userspace */
+#define OPTEE_MSG_RPC_SHM_TYPE_GLOBAL 2
+
+/*
+ * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
+ *
+ * [in] param[0].u.value.a type of memory one of
+ * OPTEE_MSG_RPC_SHM_TYPE_* above
+ * [in] param[0].u.value.b value of shared memory reference
+ * returned in param[0].u.tmem.shm_ref
+ * above
+ */
+#define OPTEE_MSG_RPC_CMD_SHM_FREE 7
+
+/*
+ * Register timestamp buffer
+ *
+ * [in] param[0].u.value.a Subcommand (register buffer, unregister buffer)
+ * [in] param[0].u.value.b Physical address of timestamp buffer
+ * [in] param[0].u.value.c Size of buffer
+ */
+#define OPTEE_MSG_RPC_CMD_BENCH_REG 20
+#endif /* _OPTEE_MSG_H */
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
new file mode 100644
index 00000000..35e79386
--- /dev/null
+++ b/drivers/tee/optee/optee_private.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef OPTEE_PRIVATE_H
+#define OPTEE_PRIVATE_H
+
+#include <linux/arm-smccc.h>
+#include <linux/semaphore.h>
+#include <linux/tee_drv.h>
+#include <linux/types.h>
+#include "optee_msg.h"
+
+#define OPTEE_MAX_ARG_SIZE 1024
+
+/* Some Global Platform error codes used in this driver */
+#define TEEC_SUCCESS 0x00000000
+#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
+#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
+#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
+
+#define TEEC_ORIGIN_COMMS 0x00000002
+
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+ unsigned long, unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ struct arm_smccc_res *);
+
+struct optee_call_queue {
+ /* Serializes access to this struct */
+ struct mutex mutex;
+ struct list_head waiters;
+};
+
+struct optee_wait_queue {
+ /* Serializes access to this struct */
+ struct mutex mu;
+ struct list_head db;
+};
+
+/**
+ * struct optee_supp - supplicant synchronization struct
+ * @ctx the context of current connected supplicant.
+ * if !NULL the supplicant device is available for use,
+ * else busy
+ * @mutex: held while accessing content of this struct
+ * @req_id: current request id if supplicant is doing synchronous
+ * communication, else -1
+ * @reqs: queued request not yet retrieved by supplicant
+ * @idr: IDR holding all requests currently being processed
+ * by supplicant
+ * @reqs_c: completion used by supplicant when waiting for a
+ * request to be queued.
+ */
+struct optee_supp {
+ /* Serializes access to this struct */
+ struct mutex mutex;
+ struct tee_context *ctx;
+
+ int req_id;
+ struct list_head reqs;
+ struct idr idr;
+ struct completion reqs_c;
+};
+
+/**
+ * struct optee - main service struct
+ * @supp_teedev: supplicant device
+ * @teedev: client device
+ * @invoke_fn: function to issue smc or hvc
+ * @call_queue: queue of threads waiting to call @invoke_fn
+ * @wait_queue: queue of threads from secure world waiting for a
+ * secure world sync object
+ * @supp: supplicant synchronization struct for RPC to supplicant
+ * @pool: shared memory pool
+ * @memremaped_shm virtual address of memory in shared memory pool
+ * @sec_caps: secure world capabilities defined by
+ * OPTEE_SMC_SEC_CAP_* in optee_smc.h
+ */
+struct optee {
+ struct tee_device *supp_teedev;
+ struct tee_device *teedev;
+ optee_invoke_fn *invoke_fn;
+ struct optee_call_queue call_queue;
+ struct optee_wait_queue wait_queue;
+ struct optee_supp supp;
+ struct tee_shm_pool *pool;
+ void *memremaped_shm;
+ u32 sec_caps;
+};
+
+struct optee_session {
+ struct list_head list_node;
+ u32 session_id;
+};
+
+struct optee_context_data {
+ /* Serializes access to this struct */
+ struct mutex mutex;
+ struct list_head sess_list;
+};
+
+struct optee_rpc_param {
+ u32 a0;
+ u32 a1;
+ u32 a2;
+ u32 a3;
+ u32 a4;
+ u32 a5;
+ u32 a6;
+ u32 a7;
+};
+
+/* Holds context that is preserved during one STD call */
+struct optee_call_ctx {
+ /* information about pages list used in last allocation */
+ void *pages_list;
+ size_t num_entries;
+};
+
+void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
+ struct optee_call_ctx *call_ctx);
+void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx);
+
+void optee_wait_queue_init(struct optee_wait_queue *wq);
+void optee_wait_queue_exit(struct optee_wait_queue *wq);
+
+u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+ struct tee_param *param);
+
+int optee_supp_read(struct tee_context *ctx, void __user *buf, size_t len);
+int optee_supp_write(struct tee_context *ctx, void __user *buf, size_t len);
+void optee_supp_init(struct optee_supp *supp);
+void optee_supp_uninit(struct optee_supp *supp);
+void optee_supp_release(struct optee_supp *supp);
+
+int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+ struct tee_param *param);
+int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+ struct tee_param *param);
+
+u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
+int optee_open_session(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param);
+int optee_close_session(struct tee_context *ctx, u32 session);
+int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ struct tee_param *param);
+int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
+
+void optee_enable_shm_cache(struct optee *optee);
+void optee_disable_shm_cache(struct optee *optee);
+
+int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ struct page **pages, size_t num_pages,
+ unsigned long start);
+int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
+
+int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
+ struct page **pages, size_t num_pages,
+ unsigned long start);
+int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
+
+int optee_from_msg_param(struct tee_param *params, size_t num_params,
+ const struct optee_msg_param *msg_params);
+int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+ const struct tee_param *params);
+
+u64 *optee_allocate_pages_list(size_t num_entries);
+void optee_free_pages_list(void *array, size_t num_entries);
+void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
+ size_t page_offset);
+
+/*
+ * Small helpers
+ */
+
+static inline void *reg_pair_to_ptr(u32 reg0, u32 reg1)
+{
+ return (void *)(unsigned long)(((u64)reg0 << 32) | reg1);
+}
+
+static inline void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
+{
+ *reg0 = val >> 32;
+ *reg1 = val;
+}
+
+#endif /*OPTEE_PRIVATE_H*/
diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
new file mode 100644
index 00000000..bbf0cf02
--- /dev/null
+++ b/drivers/tee/optee/optee_smc.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPTEE_SMC_H
+#define OPTEE_SMC_H
+
+#include <linux/arm-smccc.h>
+#include <linux/bitops.h>
+
+#define OPTEE_SMC_STD_CALL_VAL(func_num) \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+#define OPTEE_SMC_FAST_CALL_VAL(func_num) \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+
+/*
+ * Function specified by SMC Calling convention.
+ */
+#define OPTEE_SMC_FUNCID_CALLS_COUNT 0xFF00
+#define OPTEE_SMC_CALLS_COUNT \
+ ARM_SMCCC_CALL_VAL(OPTEE_SMC_FAST_CALL, SMCCC_SMC_32, \
+ SMCCC_OWNER_TRUSTED_OS_END, \
+ OPTEE_SMC_FUNCID_CALLS_COUNT)
+
+/*
+ * Normal cached memory (write-back), shareable for SMP systems and not
+ * shareable for UP systems.
+ */
+#define OPTEE_SMC_SHM_CACHED 1
+
+/*
+ * a0..a7 is used as register names in the descriptions below, on arm32
+ * that translates to r0..r7 and on arm64 to w0..w7. In both cases it's
+ * 32-bit registers.
+ */
+
+/*
+ * Function specified by SMC Calling convention
+ *
+ * Return one of the following UIDs if using API specified in this file
+ * without further extentions:
+ * 65cb6b93-af0c-4617-8ed6-644a8d1140f8
+ * see also OPTEE_SMC_UID_* in optee_msg.h
+ */
+#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
+#define OPTEE_SMC_CALLS_UID \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+ OPTEE_SMC_FUNCID_CALLS_UID)
+
+/*
+ * Function specified by SMC Calling convention
+ *
+ * Returns 2.0 if using API specified in this file without further extentions.
+ * see also OPTEE_MSG_REVISION_* in optee_msg.h
+ */
+#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
+#define OPTEE_SMC_CALLS_REVISION \
+ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+ ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+ OPTEE_SMC_FUNCID_CALLS_REVISION)
+
+struct optee_smc_calls_revision_result {
+ unsigned long major;
+ unsigned long minor;
+ unsigned long reserved0;
+ unsigned long reserved1;
+};
+
+/*
+ * Get UUID of Trusted OS.
+ *
+ * Used by non-secure world to figure out which Trusted OS is installed.
+ * Note that returned UUID is the UUID of the Trusted OS, not of the API.
+ *
+ * Returns UUID in a0-4 in the same way as OPTEE_SMC_CALLS_UID
+ * described above.
+ */
+#define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID
+#define OPTEE_SMC_CALL_GET_OS_UUID \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID)
+
+/*
+ * Get revision of Trusted OS.
+ *
+ * Used by non-secure world to figure out which version of the Trusted OS
+ * is installed. Note that the returned revision is the revision of the
+ * Trusted OS, not of the API.
+ *
+ * Returns revision in a0-1 in the same way as OPTEE_SMC_CALLS_REVISION
+ * described above. May optionally return a 32-bit build identifier in a2,
+ * with zero meaning unspecified.
+ */
+#define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION
+#define OPTEE_SMC_CALL_GET_OS_REVISION \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION)
+
+struct optee_smc_call_get_os_revision_result {
+ unsigned long major;
+ unsigned long minor;
+ unsigned long build_id;
+ unsigned long reserved1;
+};
+
+/*
+ * Call with struct optee_msg_arg as argument
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
+ * a1 Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
+ * a2 Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
+ * a3 Cache settings, not used if physical pointer is in a predefined shared
+ * memory area else per OPTEE_SMC_SHM_*
+ * a4-6 Not used
+ * a7 Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0 Return value, OPTEE_SMC_RETURN_*
+ * a1-3 Not used
+ * a4-7 Preserved
+ *
+ * OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage:
+ * a0 Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT
+ * a1-3 Preserved
+ * a4-7 Preserved
+ *
+ * RPC return register usage:
+ * a0 Return value, OPTEE_SMC_RETURN_IS_RPC(val)
+ * a1-2 RPC parameters
+ * a3-7 Resume information, must be preserved
+ *
+ * Possible return values:
+ * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this
+ * function.
+ * OPTEE_SMC_RETURN_OK Call completed, result updated in
+ * the previously supplied struct
+ * optee_msg_arg.
+ * OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded,
+ * try again later.
+ * OPTEE_SMC_RETURN_EBADADDR Bad physcial pointer to struct
+ * optee_msg_arg.
+ * OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg
+ * OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal
+ * world.
+ */
+#define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG
+#define OPTEE_SMC_CALL_WITH_ARG \
+ OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG)
+
+/*
+ * Get Shared Memory Config
+ *
+ * Returns the Secure/Non-secure shared memory config.
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG
+ * a1-6 Not used
+ * a7 Hypervisor Client ID register
+ *
+ * Have config return register usage:
+ * a0 OPTEE_SMC_RETURN_OK
+ * a1 Physical address of start of SHM
+ * a2 Size of of SHM
+ * a3 Cache settings of memory, as defined by the
+ * OPTEE_SMC_SHM_* values above
+ * a4-7 Preserved
+ *
+ * Not available register usage:
+ * a0 OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-3 Not used
+ * a4-7 Preserved
+ */
+#define OPTEE_SMC_FUNCID_GET_SHM_CONFIG 7
+#define OPTEE_SMC_GET_SHM_CONFIG \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG)
+
+struct optee_smc_get_shm_config_result {
+ unsigned long status;
+ unsigned long start;
+ unsigned long size;
+ unsigned long settings;
+};
+
+/*
+ * Exchanges capabilities between normal world and secure world
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES
+ * a1 bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_*
+ * a2-6 Not used
+ * a7 Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0 OPTEE_SMC_RETURN_OK
+ * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
+ * a2-7 Preserved
+ *
+ * Error return register usage:
+ * a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world
+ * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
+ * a2-7 Preserved
+ */
+/* Normal world works as a uniprocessor system */
+#define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR BIT(0)
+/* Secure world has reserved shared memory for normal world to use */
+#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM BIT(0)
+/* Secure world can communicate via previously unregistered shared memory */
+#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM BIT(1)
+
+/*
+ * Secure world supports commands "register/unregister shared memory",
+ * secure world accepts command buffers located in any parts of non-secure RAM
+ */
+#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2)
+
+#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
+#define OPTEE_SMC_EXCHANGE_CAPABILITIES \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
+
+struct optee_smc_exchange_capabilities_result {
+ unsigned long status;
+ unsigned long capabilities;
+ unsigned long reserved0;
+ unsigned long reserved1;
+};
+
+/*
+ * Disable and empties cache of shared memory objects
+ *
+ * Secure world can cache frequently used shared memory objects, for
+ * example objects used as RPC arguments. When secure world is idle this
+ * function returns one shared memory reference to free. To disable the
+ * cache and free all cached objects this function has to be called until
+ * it returns OPTEE_SMC_RETURN_ENOTAVAIL.
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE
+ * a1-6 Not used
+ * a7 Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0 OPTEE_SMC_RETURN_OK
+ * a1 Upper 32bit of a 64bit Shared memory cookie
+ * a2 Lower 32bit of a 64bit Shared memory cookie
+ * a3-7 Preserved
+ *
+ * Cache empty return register usage:
+ * a0 OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-7 Preserved
+ *
+ * Not idle return register usage:
+ * a0 OPTEE_SMC_RETURN_EBUSY
+ * a1-7 Preserved
+ */
+#define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE 10
+#define OPTEE_SMC_DISABLE_SHM_CACHE \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE)
+
+struct optee_smc_disable_shm_cache_result {
+ unsigned long status;
+ unsigned long shm_upper32;
+ unsigned long shm_lower32;
+ unsigned long reserved0;
+};
+
+/*
+ * Enable cache of shared memory objects
+ *
+ * Secure world can cache frequently used shared memory objects, for
+ * example objects used as RPC arguments. When secure world is idle this
+ * function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If
+ * secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned.
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE
+ * a1-6 Not used
+ * a7 Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0 OPTEE_SMC_RETURN_OK
+ * a1-7 Preserved
+ *
+ * Not idle return register usage:
+ * a0 OPTEE_SMC_RETURN_EBUSY
+ * a1-7 Preserved
+ */
+#define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE 11
+#define OPTEE_SMC_ENABLE_SHM_CACHE \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
+
+/*
+ * Resume from RPC (for example after processing a foreign interrupt)
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
+ * a1-3 Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned
+ * OPTEE_SMC_RETURN_RPC in a0
+ *
+ * Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above.
+ *
+ * Possible return values
+ * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this
+ * function.
+ * OPTEE_SMC_RETURN_OK Original call completed, result
+ * updated in the previously supplied.
+ * struct optee_msg_arg
+ * OPTEE_SMC_RETURN_RPC Call suspended by RPC call to normal
+ * world.
+ * OPTEE_SMC_RETURN_ERESUME Resume failed, the opaque resume
+ * information was corrupt.
+ */
+#define OPTEE_SMC_FUNCID_RETURN_FROM_RPC 3
+#define OPTEE_SMC_CALL_RETURN_FROM_RPC \
+ OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC)
+
+#define OPTEE_SMC_RETURN_RPC_PREFIX_MASK 0xFFFF0000
+#define OPTEE_SMC_RETURN_RPC_PREFIX 0xFFFF0000
+#define OPTEE_SMC_RETURN_RPC_FUNC_MASK 0x0000FFFF
+
+#define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \
+ ((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK)
+
+#define OPTEE_SMC_RPC_VAL(func) ((func) | OPTEE_SMC_RETURN_RPC_PREFIX)
+
+/*
+ * Allocate memory for RPC parameter passing. The memory is used to hold a
+ * struct optee_msg_arg.
+ *
+ * "Call" register usage:
+ * a0 This value, OPTEE_SMC_RETURN_RPC_ALLOC
+ * a1 Size in bytes of required argument memory
+ * a2 Not used
+ * a3 Resume information, must be preserved
+ * a4-5 Not used
+ * a6-7 Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1 Upper 32bits of 64bit physical pointer to allocated
+ * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ * be allocated.
+ * a2 Lower 32bits of 64bit physical pointer to allocated
+ * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ * be allocated
+ * a3 Preserved
+ * a4 Upper 32bits of 64bit Shared memory cookie used when freeing
+ * the memory or doing an RPC
+ * a5 Lower 32bits of 64bit Shared memory cookie used when freeing
+ * the memory or doing an RPC
+ * a6-7 Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_ALLOC 0
+#define OPTEE_SMC_RETURN_RPC_ALLOC \
+ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC)
+
+/*
+ * Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC
+ *
+ * "Call" register usage:
+ * a0 This value, OPTEE_SMC_RETURN_RPC_FREE
+ * a1 Upper 32bits of 64bit shared memory cookie belonging to this
+ * argument memory
+ * a2 Lower 32bits of 64bit shared memory cookie belonging to this
+ * argument memory
+ * a3-7 Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-2 Not used
+ * a3-7 Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_FREE 2
+#define OPTEE_SMC_RETURN_RPC_FREE \
+ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
+
+/*
+ * Deliver foreign interrupt to normal world.
+ *
+ * "Call" register usage:
+ * a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
+ * a1-7 Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-7 Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
+#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
+ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
+
+/*
+ * Do an RPC request. The supplied struct optee_msg_arg tells which
+ * request to do and the parameters for the request. The following fields
+ * are used (the rest are unused):
+ * - cmd the Request ID
+ * - ret return value of the request, filled in by normal world
+ * - num_params number of parameters for the request
+ * - params the parameters
+ * - param_attrs attributes of the parameters
+ *
+ * "Call" register usage:
+ * a0 OPTEE_SMC_RETURN_RPC_CMD
+ * a1 Upper 32bit of a 64bit Shared memory cookie holding a
+ * struct optee_msg_arg, must be preserved, only the data should
+ * be updated
+ * a2 Lower 32bit of a 64bit Shared memory cookie holding a
+ * struct optee_msg_arg, must be preserved, only the data should
+ * be updated
+ * a3-7 Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-2 Not used
+ * a3-7 Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_CMD 5
+#define OPTEE_SMC_RETURN_RPC_CMD \
+ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD)
+
+/* Returned in a0 */
+#define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
+
+/* Returned in a0 only from Trusted OS functions */
+#define OPTEE_SMC_RETURN_OK 0x0
+#define OPTEE_SMC_RETURN_ETHREAD_LIMIT 0x1
+#define OPTEE_SMC_RETURN_EBUSY 0x2
+#define OPTEE_SMC_RETURN_ERESUME 0x3
+#define OPTEE_SMC_RETURN_EBADADDR 0x4
+#define OPTEE_SMC_RETURN_EBADCMD 0x5
+#define OPTEE_SMC_RETURN_ENOMEM 0x6
+#define OPTEE_SMC_RETURN_ENOTAVAIL 0x7
+#define OPTEE_SMC_RETURN_IS_RPC(ret) __optee_smc_return_is_rpc((ret))
+
+static inline bool __optee_smc_return_is_rpc(u32 ret)
+{
+ return ret != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION &&
+ (ret & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) ==
+ OPTEE_SMC_RETURN_RPC_PREFIX;
+}
+
+#endif /* OPTEE_SMC_H */
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
new file mode 100644
index 00000000..67b22886
--- /dev/null
+++ b/drivers/tee/optee/rpc.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include "optee_bench.h"
+#include "optee_private.h"
+#include "optee_smc.h"
+
+struct wq_entry {
+ struct list_head link;
+ struct completion c;
+ u32 key;
+};
+
+void optee_wait_queue_init(struct optee_wait_queue *priv)
+{
+ mutex_init(&priv->mu);
+ INIT_LIST_HEAD(&priv->db);
+}
+
+void optee_wait_queue_exit(struct optee_wait_queue *priv)
+{
+ mutex_destroy(&priv->mu);
+}
+
+static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
+{
+ struct timespec64 ts;
+
+ if (arg->num_params != 1)
+ goto bad;
+ if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
+ OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
+ goto bad;
+
+ ktime_get_real_ts64(&ts);
+ arg->params[0].u.value.a = ts.tv_sec;
+ arg->params[0].u.value.b = ts.tv_nsec;
+
+ arg->ret = TEEC_SUCCESS;
+ return;
+bad:
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+}
+
+static struct wq_entry *wq_entry_get(struct optee_wait_queue *wq, u32 key)
+{
+ struct wq_entry *w;
+
+ mutex_lock(&wq->mu);
+
+ list_for_each_entry(w, &wq->db, link)
+ if (w->key == key)
+ goto out;
+
+ w = kmalloc(sizeof(*w), GFP_KERNEL);
+ if (w) {
+ init_completion(&w->c);
+ w->key = key;
+ list_add_tail(&w->link, &wq->db);
+ }
+out:
+ mutex_unlock(&wq->mu);
+ return w;
+}
+
+static void wq_sleep(struct optee_wait_queue *wq, u32 key)
+{
+ struct wq_entry *w = wq_entry_get(wq, key);
+
+ if (w) {
+ wait_for_completion(&w->c);
+ mutex_lock(&wq->mu);
+ list_del(&w->link);
+ mutex_unlock(&wq->mu);
+ kfree(w);
+ }
+}
+
+static void wq_wakeup(struct optee_wait_queue *wq, u32 key)
+{
+ struct wq_entry *w = wq_entry_get(wq, key);
+
+ if (w)
+ complete(&w->c);
+}
+
+static void handle_rpc_func_cmd_wq(struct optee *optee,
+ struct optee_msg_arg *arg)
+{
+ if (arg->num_params != 1)
+ goto bad;
+
+ if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
+ OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
+ goto bad;
+
+ switch (arg->params[0].u.value.a) {
+ case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP:
+ wq_sleep(&optee->wait_queue, arg->params[0].u.value.b);
+ break;
+ case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP:
+ wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b);
+ break;
+ default:
+ goto bad;
+ }
+
+ arg->ret = TEEC_SUCCESS;
+ return;
+bad:
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+}
+
+static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
+{
+ u32 msec_to_wait;
+
+ if (arg->num_params != 1)
+ goto bad;
+
+ if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
+ OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
+ goto bad;
+
+ msec_to_wait = arg->params[0].u.value.a;
+
+ /* Go to interruptible sleep */
+ msleep_interruptible(msec_to_wait);
+
+ arg->ret = TEEC_SUCCESS;
+ return;
+bad:
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+}
+
+static void handle_rpc_supp_cmd(struct tee_context *ctx,
+ struct optee_msg_arg *arg)
+{
+ struct tee_param *params;
+
+ arg->ret_origin = TEEC_ORIGIN_COMMS;
+
+ params = kmalloc_array(arg->num_params, sizeof(struct tee_param),
+ GFP_KERNEL);
+ if (!params) {
+ arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+ return;
+ }
+
+ if (optee_from_msg_param(params, arg->num_params, arg->params)) {
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
+
+ if (optee_to_msg_param(arg->params, arg->num_params, params))
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+out:
+ kfree(params);
+}
+
+static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
+{
+ u32 ret;
+ struct tee_param param;
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct tee_shm *shm;
+
+ param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+ param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
+ param.u.value.b = sz;
+ param.u.value.c = 0;
+
+ ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, &param);
+ if (ret)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_lock(&optee->supp.mutex);
+ /* Increases count as secure world doesn't have a reference */
+ shm = tee_shm_get_from_id(optee->supp.ctx, param.u.value.c);
+ mutex_unlock(&optee->supp.mutex);
+ return shm;
+}
+
+static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
+ struct optee_msg_arg *arg,
+ struct optee_call_ctx *call_ctx)
+{
+ phys_addr_t pa;
+ struct tee_shm *shm;
+ size_t sz;
+ size_t n;
+
+ arg->ret_origin = TEEC_ORIGIN_COMMS;
+
+ if (!arg->num_params ||
+ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ for (n = 1; n < arg->num_params; n++) {
+ if (arg->params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE) {
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ return;
+ }
+ }
+
+ sz = arg->params[0].u.value.b;
+ switch (arg->params[0].u.value.a) {
+ case OPTEE_MSG_RPC_SHM_TYPE_APPL:
+ shm = cmd_alloc_suppl(ctx, sz);
+ break;
+ case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
+ shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
+ break;
+ case OPTEE_MSG_RPC_SHM_TYPE_GLOBAL:
+ shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ break;
+ default:
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ if (IS_ERR(shm)) {
+ arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+ return;
+ }
+
+ if (tee_shm_get_pa(shm, 0, &pa)) {
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ goto bad;
+ }
+
+ sz = tee_shm_get_size(shm);
+
+ if (tee_shm_is_registered(shm)) {
+ struct page **pages;
+ u64 *pages_list;
+ size_t page_num;
+
+ pages = tee_shm_get_pages(shm, &page_num);
+ if (!pages || !page_num) {
+ arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+ goto bad;
+ }
+
+ pages_list = optee_allocate_pages_list(page_num);
+ if (!pages_list) {
+ arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+ goto bad;
+ }
+
+ call_ctx->pages_list = pages_list;
+ call_ctx->num_entries = page_num;
+
+ arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
+ OPTEE_MSG_ATTR_NONCONTIG;
+ /*
+ * In the least bits of u.tmem.buf_ptr we store buffer offset
+ * from 4k page, as described in OP-TEE ABI.
+ */
+ arg->params[0].u.tmem.buf_ptr = virt_to_phys(pages_list) |
+ (tee_shm_get_page_offset(shm) &
+ (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
+ arg->params[0].u.tmem.size = tee_shm_get_size(shm);
+ arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
+
+ optee_fill_pages_list(pages_list, pages, page_num,
+ tee_shm_get_page_offset(shm));
+ } else {
+ arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
+ arg->params[0].u.tmem.buf_ptr = pa;
+ arg->params[0].u.tmem.size = sz;
+ arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
+ }
+
+ arg->ret = TEEC_SUCCESS;
+ return;
+bad:
+ tee_shm_free(shm);
+}
+
+static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
+{
+ struct tee_param param;
+
+ param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+ param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
+ param.u.value.b = tee_shm_get_id(shm);
+ param.u.value.c = 0;
+
+ /*
+ * Match the tee_shm_get_from_id() in cmd_alloc_suppl() as secure
+ * world has released its reference.
+ *
+ * It's better to do this before sending the request to supplicant
+ * as we'd like to let the process doing the initial allocation to
+ * do release the last reference too in order to avoid stacking
+ * many pending fput() on the client process. This could otherwise
+ * happen if secure world does many allocate and free in a single
+ * invoke.
+ */
+ tee_shm_put(shm);
+
+ optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, &param);
+}
+
+static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
+ struct optee_msg_arg *arg)
+{
+ struct tee_shm *shm;
+
+ arg->ret_origin = TEEC_ORIGIN_COMMS;
+
+ if (arg->num_params != 1 ||
+ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b;
+ switch (arg->params[0].u.value.a) {
+ case OPTEE_MSG_RPC_SHM_TYPE_APPL:
+ cmd_free_suppl(ctx, shm);
+ break;
+ case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
+ case OPTEE_MSG_RPC_SHM_TYPE_GLOBAL:
+ tee_shm_free(shm);
+ break;
+ default:
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ }
+ arg->ret = TEEC_SUCCESS;
+}
+
+static void free_pages_list(struct optee_call_ctx *call_ctx)
+{
+ if (call_ctx->pages_list) {
+ optee_free_pages_list(call_ctx->pages_list,
+ call_ctx->num_entries);
+ call_ctx->pages_list = NULL;
+ call_ctx->num_entries = 0;
+ }
+}
+
+void optee_rpc_finalize_call(struct optee_call_ctx *call_ctx)
+{
+ free_pages_list(call_ctx);
+}
+
+static void handle_rpc_func_cmd_bm_reg(struct optee_msg_arg *arg)
+{
+ u64 size;
+ u64 type;
+ u64 paddr;
+
+ if (arg->num_params != 1)
+ goto bad;
+
+ if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
+ OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
+ goto bad;
+
+ type = arg->params[0].u.value.a;
+ switch (type) {
+ case OPTEE_MSG_RPC_CMD_BENCH_REG_NEW:
+ size = arg->params[0].u.value.c;
+ paddr = arg->params[0].u.value.b;
+ down_write(&optee_bench_ts_rwsem);
+ optee_bench_ts_global =
+ memremap(paddr, size, MEMREMAP_WB);
+ if (!optee_bench_ts_global) {
+ up_write(&optee_bench_ts_rwsem);
+ goto bad;
+ }
+ up_write(&optee_bench_ts_rwsem);
+ break;
+ case OPTEE_MSG_RPC_CMD_BENCH_REG_DEL:
+ down_write(&optee_bench_ts_rwsem);
+ if (optee_bench_ts_global)
+ memunmap(optee_bench_ts_global);
+ optee_bench_ts_global = NULL;
+ up_write(&optee_bench_ts_rwsem);
+ break;
+ default:
+ goto bad;
+ }
+
+ arg->ret = TEEC_SUCCESS;
+ return;
+bad:
+ arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+}
+
+static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
+ struct tee_shm *shm,
+ struct optee_call_ctx *call_ctx)
+{
+ struct optee_msg_arg *arg;
+
+ arg = tee_shm_get_va(shm, 0);
+ if (IS_ERR(arg)) {
+ pr_err("%s: tee_shm_get_va %p failed\n", __func__, shm);
+ return;
+ }
+
+ switch (arg->cmd) {
+ case OPTEE_MSG_RPC_CMD_GET_TIME:
+ handle_rpc_func_cmd_get_time(arg);
+ break;
+ case OPTEE_MSG_RPC_CMD_WAIT_QUEUE:
+ handle_rpc_func_cmd_wq(optee, arg);
+ break;
+ case OPTEE_MSG_RPC_CMD_SUSPEND:
+ handle_rpc_func_cmd_wait(arg);
+ break;
+ case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
+ free_pages_list(call_ctx);
+ handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
+ break;
+ case OPTEE_MSG_RPC_CMD_SHM_FREE:
+ handle_rpc_func_cmd_shm_free(ctx, arg);
+ break;
+ case OPTEE_MSG_RPC_CMD_BENCH_REG:
+ handle_rpc_func_cmd_bm_reg(arg);
+ break;
+ default:
+ handle_rpc_supp_cmd(ctx, arg);
+ }
+}
+
+/**
+ * optee_handle_rpc() - handle RPC from secure world
+ * @ctx: context doing the RPC
+ * @param: value of registers for the RPC
+ * @call_ctx: call context. Preserved during one OP-TEE invocation
+ *
+ * Result of RPC is written back into @param.
+ */
+void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
+ struct optee_call_ctx *call_ctx)
+{
+ struct tee_device *teedev = ctx->teedev;
+ struct optee *optee = tee_get_drvdata(teedev);
+ struct tee_shm *shm;
+ phys_addr_t pa;
+
+ switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
+ case OPTEE_SMC_RPC_FUNC_ALLOC:
+ shm = tee_shm_alloc(ctx, param->a1, TEE_SHM_MAPPED);
+ if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
+ reg_pair_from_64(&param->a1, &param->a2, pa);
+ reg_pair_from_64(&param->a4, &param->a5,
+ (unsigned long)shm);
+ } else {
+ param->a1 = 0;
+ param->a2 = 0;
+ param->a4 = 0;
+ param->a5 = 0;
+ }
+ break;
+ case OPTEE_SMC_RPC_FUNC_FREE:
+ shm = reg_pair_to_ptr(param->a1, param->a2);
+ tee_shm_free(shm);
+ break;
+ case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
+ /*
+ * A foreign interrupt was raised while secure world was
+ * executing, since they are handled in Linux a dummy RPC is
+ * performed to let Linux take the interrupt through the normal
+ * vector.
+ */
+ break;
+ case OPTEE_SMC_RPC_FUNC_CMD:
+ shm = reg_pair_to_ptr(param->a1, param->a2);
+ handle_rpc_func_cmd(ctx, optee, shm, call_ctx);
+ break;
+ default:
+ pr_warn("Unknown RPC func 0x%x\n",
+ (u32)OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0));
+ break;
+ }
+
+ param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+}
diff --git a/drivers/tee/optee/shm_pool.c b/drivers/tee/optee/shm_pool.c
new file mode 100644
index 00000000..49397813
--- /dev/null
+++ b/drivers/tee/optee/shm_pool.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2017, EPAM Systems
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/genalloc.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include "optee_private.h"
+#include "optee_smc.h"
+#include "shm_pool.h"
+
+static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
+ struct tee_shm *shm, size_t size)
+{
+ unsigned int order = get_order(size);
+ struct page *page;
+
+ page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
+ if (!page)
+ return -ENOMEM;
+
+ shm->kaddr = page_address(page);
+ shm->paddr = page_to_phys(page);
+ shm->size = PAGE_SIZE << order;
+
+ return 0;
+}
+
+static void pool_op_free(struct tee_shm_pool_mgr *poolm,
+ struct tee_shm *shm)
+{
+ free_pages((unsigned long)shm->kaddr, get_order(shm->size));
+ shm->kaddr = NULL;
+}
+
+static void pool_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm)
+{
+ kfree(poolm);
+}
+
+static const struct tee_shm_pool_mgr_ops pool_ops = {
+ .alloc = pool_op_alloc,
+ .free = pool_op_free,
+ .destroy_poolmgr = pool_op_destroy_poolmgr,
+};
+
+/**
+ * optee_shm_pool_alloc_pages() - create page-based allocator pool
+ *
+ * This pool is used when OP-TEE supports dymanic SHM. In this case
+ * command buffers and such are allocated from kernel's own memory.
+ */
+struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void)
+{
+ struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+
+ if (!mgr)
+ return ERR_PTR(-ENOMEM);
+
+ mgr->ops = &pool_ops;
+
+ return mgr;
+}
diff --git a/drivers/tee/optee/shm_pool.h b/drivers/tee/optee/shm_pool.h
new file mode 100644
index 00000000..4e753c3b
--- /dev/null
+++ b/drivers/tee/optee/shm_pool.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2016, EPAM Systems
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef SHM_POOL_H
+#define SHM_POOL_H
+
+#include <linux/tee_drv.h>
+
+struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void);
+
+#endif
diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
new file mode 100644
index 00000000..df35fc01
--- /dev/null
+++ b/drivers/tee/optee/supp.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include "optee_private.h"
+
+struct optee_supp_req {
+ struct list_head link;
+
+ bool busy;
+ u32 func;
+ u32 ret;
+ size_t num_params;
+ struct tee_param *param;
+
+ struct completion c;
+};
+
+void optee_supp_init(struct optee_supp *supp)
+{
+ memset(supp, 0, sizeof(*supp));
+ mutex_init(&supp->mutex);
+ init_completion(&supp->reqs_c);
+ idr_init(&supp->idr);
+ INIT_LIST_HEAD(&supp->reqs);
+ supp->req_id = -1;
+}
+
+void optee_supp_uninit(struct optee_supp *supp)
+{
+ mutex_destroy(&supp->mutex);
+ idr_destroy(&supp->idr);
+}
+
+void optee_supp_release(struct optee_supp *supp)
+{
+ int id;
+ struct optee_supp_req *req;
+ struct optee_supp_req *req_tmp;
+
+ mutex_lock(&supp->mutex);
+
+ /* Abort all request retrieved by supplicant */
+ idr_for_each_entry(&supp->idr, req, id) {
+ req->busy = false;
+ idr_remove(&supp->idr, id);
+ req->ret = TEEC_ERROR_COMMUNICATION;
+ complete(&req->c);
+ }
+
+ /* Abort all queued requests */
+ list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
+ list_del(&req->link);
+ req->ret = TEEC_ERROR_COMMUNICATION;
+ complete(&req->c);
+ }
+
+ supp->ctx = NULL;
+ supp->req_id = -1;
+
+ mutex_unlock(&supp->mutex);
+}
+
+/**
+ * optee_supp_thrd_req() - request service from supplicant
+ * @ctx: context doing the request
+ * @func: function requested
+ * @num_params: number of elements in @param array
+ * @param: parameters for function
+ *
+ * Returns result of operation to be passed to secure world
+ */
+u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+ struct tee_param *param)
+
+{
+ struct optee *optee = tee_get_drvdata(ctx->teedev);
+ struct optee_supp *supp = &optee->supp;
+ struct optee_supp_req *req = kzalloc(sizeof(*req), GFP_KERNEL);
+ bool interruptable;
+ u32 ret;
+
+ if (!req)
+ return TEEC_ERROR_OUT_OF_MEMORY;
+
+ init_completion(&req->c);
+ req->func = func;
+ req->num_params = num_params;
+ req->param = param;
+
+ /* Insert the request in the request list */
+ mutex_lock(&supp->mutex);
+ list_add_tail(&req->link, &supp->reqs);
+ mutex_unlock(&supp->mutex);
+
+ /* Tell an eventual waiter there's a new request */
+ complete(&supp->reqs_c);
+
+ /*
+ * Wait for supplicant to process and return result, once we've
+ * returned from wait_for_completion(&req->c) successfully we have
+ * exclusive access again.
+ */
+ while (wait_for_completion_interruptible(&req->c)) {
+ mutex_lock(&supp->mutex);
+ interruptable = !supp->ctx;
+ if (interruptable) {
+ /*
+ * There's no supplicant available and since the
+ * supp->mutex currently is held none can
+ * become available until the mutex released
+ * again.
+ *
+ * Interrupting an RPC to supplicant is only
+ * allowed as a way of slightly improving the user
+ * experience in case the supplicant hasn't been
+ * started yet. During normal operation the supplicant
+ * will serve all requests in a timely manner and
+ * interrupting then wouldn't make sense.
+ */
+ interruptable = !req->busy;
+ if (!req->busy)
+ list_del(&req->link);
+ }
+ mutex_unlock(&supp->mutex);
+
+ if (interruptable) {
+ req->ret = TEEC_ERROR_COMMUNICATION;
+ break;
+ }
+ }
+
+ ret = req->ret;
+ kfree(req);
+
+ return ret;
+}
+
+static struct optee_supp_req *supp_pop_entry(struct optee_supp *supp,
+ int num_params, int *id)
+{
+ struct optee_supp_req *req;
+
+ if (supp->req_id != -1) {
+ /*
+ * Supplicant should not mix synchronous and asnynchronous
+ * requests.
+ */
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (list_empty(&supp->reqs))
+ return NULL;
+
+ req = list_first_entry(&supp->reqs, struct optee_supp_req, link);
+
+ if (num_params < req->num_params) {
+ /* Not enough room for parameters */
+ return ERR_PTR(-EINVAL);
+ }
+
+ *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
+ if (*id < 0)
+ return ERR_PTR(-ENOMEM);
+
+ list_del(&req->link);
+ req->busy = true;
+
+ return req;
+}
+
+static int supp_check_recv_params(size_t num_params, struct tee_param *params,
+ size_t *num_meta)
+{
+ size_t n;
+
+ if (!num_params)
+ return -EINVAL;
+
+ /*
+ * If there's memrefs we need to decrease those as they where
+ * increased earlier and we'll even refuse to accept any below.
+ */
+ for (n = 0; n < num_params; n++)
+ if (tee_param_is_memref(params + n) && params[n].u.memref.shm)
+ tee_shm_put(params[n].u.memref.shm);
+
+ /*
+ * We only expect parameters as TEE_IOCTL_PARAM_ATTR_TYPE_NONE with
+ * or without the TEE_IOCTL_PARAM_ATTR_META bit set.
+ */
+ for (n = 0; n < num_params; n++)
+ if (params[n].attr &&
+ params[n].attr != TEE_IOCTL_PARAM_ATTR_META)
+ return -EINVAL;
+
+ /* At most we'll need one meta parameter so no need to check for more */
+ if (params->attr == TEE_IOCTL_PARAM_ATTR_META)
+ *num_meta = 1;
+ else
+ *num_meta = 0;
+
+ return 0;
+}
+
+/**
+ * optee_supp_recv() - receive request for supplicant
+ * @ctx: context receiving the request
+ * @func: requested function in supplicant
+ * @num_params: number of elements allocated in @param, updated with number
+ * used elements
+ * @param: space for parameters for @func
+ *
+ * Returns 0 on success or <0 on failure
+ */
+int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+ struct tee_param *param)
+{
+ struct tee_device *teedev = ctx->teedev;
+ struct optee *optee = tee_get_drvdata(teedev);
+ struct optee_supp *supp = &optee->supp;
+ struct optee_supp_req *req = NULL;
+ int id;
+ size_t num_meta;
+ int rc;
+
+ rc = supp_check_recv_params(*num_params, param, &num_meta);
+ if (rc)
+ return rc;
+
+ while (true) {
+ mutex_lock(&supp->mutex);
+ req = supp_pop_entry(supp, *num_params - num_meta, &id);
+ mutex_unlock(&supp->mutex);
+
+ if (req) {
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+ break;
+ }
+
+ /*
+ * If we didn't get a request we'll block in
+ * wait_for_completion() to avoid needless spinning.
+ *
+ * This is where supplicant will be hanging most of
+ * the time, let's make this interruptable so we
+ * can easily restart supplicant if needed.
+ */
+ if (wait_for_completion_interruptible(&supp->reqs_c))
+ return -ERESTARTSYS;
+ }
+
+ if (num_meta) {
+ /*
+ * tee-supplicant support meta parameters -> requsts can be
+ * processed asynchronously.
+ */
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+ TEE_IOCTL_PARAM_ATTR_META;
+ param->u.value.a = id;
+ param->u.value.b = 0;
+ param->u.value.c = 0;
+ } else {
+ mutex_lock(&supp->mutex);
+ supp->req_id = id;
+ mutex_unlock(&supp->mutex);
+ }
+
+ *func = req->func;
+ *num_params = req->num_params + num_meta;
+ memcpy(param + num_meta, req->param,
+ sizeof(struct tee_param) * req->num_params);
+
+ return 0;
+}
+
+static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
+ size_t num_params,
+ struct tee_param *param,
+ size_t *num_meta)
+{
+ struct optee_supp_req *req;
+ int id;
+ size_t nm;
+ const u32 attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
+ TEE_IOCTL_PARAM_ATTR_META;
+
+ if (!num_params)
+ return ERR_PTR(-EINVAL);
+
+ if (supp->req_id == -1) {
+ if (param->attr != attr)
+ return ERR_PTR(-EINVAL);
+ id = param->u.value.a;
+ nm = 1;
+ } else {
+ id = supp->req_id;
+ nm = 0;
+ }
+
+ req = idr_find(&supp->idr, id);
+ if (!req)
+ return ERR_PTR(-ENOENT);
+
+ if ((num_params - nm) != req->num_params)
+ return ERR_PTR(-EINVAL);
+
+ req->busy = false;
+ idr_remove(&supp->idr, id);
+ supp->req_id = -1;
+ *num_meta = nm;
+
+ return req;
+}
+
+/**
+ * optee_supp_send() - send result of request from supplicant
+ * @ctx: context sending result
+ * @ret: return value of request
+ * @num_params: number of parameters returned
+ * @param: returned parameters
+ *
+ * Returns 0 on success or <0 on failure.
+ */
+int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+ struct tee_param *param)
+{
+ struct tee_device *teedev = ctx->teedev;
+ struct optee *optee = tee_get_drvdata(teedev);
+ struct optee_supp *supp = &optee->supp;
+ struct optee_supp_req *req;
+ size_t n;
+ size_t num_meta;
+
+ mutex_lock(&supp->mutex);
+ req = supp_pop_req(supp, num_params, param, &num_meta);
+ mutex_unlock(&supp->mutex);
+
+ if (IS_ERR(req)) {
+ /* Something is wrong, let supplicant restart. */
+ return PTR_ERR(req);
+ }
+
+ /* Update out and in/out parameters */
+ for (n = 0; n < req->num_params; n++) {
+ struct tee_param *p = req->param + n;
+
+ switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ p->u.value.a = param[n + num_meta].u.value.a;
+ p->u.value.b = param[n + num_meta].u.value.b;
+ p->u.value.c = param[n + num_meta].u.value.c;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ p->u.memref.size = param[n + num_meta].u.memref.size;
+ break;
+ default:
+ break;
+ }
+ }
+ req->ret = ret;
+
+ /* Let the requesting thread continue */
+ complete(&req->c);
+
+ return 0;
+}
diff --git a/drivers/tee/tee_api/Makefile b/drivers/tee/tee_api/Makefile
new file mode 100644
index 00000000..800cbcf3
--- /dev/null
+++ b/drivers/tee/tee_api/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += tee_client_api.o
diff --git a/drivers/tee/tee_api/tee_client_api.c b/drivers/tee/tee_api/tee_client_api.c
new file mode 100644
index 00000000..a3b4093c
--- /dev/null
+++ b/drivers/tee/tee_api/tee_client_api.c
@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#define pr_fmt(fmt) "%s %d: " fmt, __func__, __LINE__
+
+#include <linux/limits.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <linux/mutex.h>
+#include <linux/file.h>
+#include <linux/syscalls.h>
+#include <linux/slab.h>
+#include "tee_client_api.h"
+#include "tee_kern.h"
+
+#define EMSG(...) pr_err(__VA_ARGS__)
+
+#ifndef __aligned
+#define __aligned(x) __attribute__((__aligned__(x)))
+#endif
+
+/* How many device sequence numbers will be tried before giving up */
+#define TEEC_MAX_DEV_SEQ 10
+
+static DEFINE_MUTEX(teec_mutex);
+
+static void teec_mutex_lock(struct mutex *mu)
+{
+ mutex_lock(mu);
+}
+
+static void teec_mutex_unlock(struct mutex *mu)
+{
+ mutex_unlock(mu);
+}
+
+
+static long tee_ioctl(struct file *filp, unsigned int cmd, void *arg)
+{
+ extern long tee_ioctl_kern(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
+ return tee_ioctl_kern(filp, cmd, (unsigned long)arg);
+}
+
+static struct file * teec_open_dev(const char *devname, const char *capabilities,
+ uint32_t *gen_caps)
+{
+ struct tee_ioctl_version_data vers;
+
+ struct file *fp = filp_open(devname, O_RDWR, 0);
+ if (IS_ERR_OR_NULL(fp)) {
+ pr_err("filp_open(\"%s\") failed: %ld", devname, PTR_ERR(fp));
+ return ERR_PTR(-ENOENT);
+ }
+
+ if (tee_ioctl(fp, TEE_IOC_VERSION, &vers)) {
+ EMSG("TEE_IOC_VERSION failed");
+ goto err;
+ }
+
+ /* We can only handle GP TEEs */
+ if (!(vers.gen_caps & TEE_GEN_CAP_GP))
+ goto err;
+
+ if (capabilities) {
+ if (strcmp(capabilities, "optee-tz") == 0) {
+ if (vers.impl_id != TEE_IMPL_ID_OPTEE)
+ goto err;
+ if (!(vers.impl_caps & TEE_OPTEE_CAP_TZ))
+ goto err;
+ } else {
+ /* Unrecognized capability requested */
+ goto err;
+ }
+ }
+
+ *gen_caps = vers.gen_caps;
+ return fp;
+err:
+ filp_close(fp, NULL);
+ return ERR_PTR(-1);
+}
+
+static int teec_shm_alloc(struct file *fp, size_t size, int *id)
+{
+ int shm_fd;
+ struct tee_ioctl_shm_alloc_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.size = size;
+ shm_fd = tee_ioctl(fp, TEE_IOC_SHM_ALLOC, &data); /*return kaddr*/
+ if (IS_ERR_OR_NULL((void *)shm_fd))
+ return shm_fd;
+
+ *id = data.id;
+ return shm_fd;
+}
+
+static int teec_shm_register(struct file *fp, void *buf, size_t size, int *id)
+{
+ int shm_fd;
+ struct tee_ioctl_shm_register_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.addr = (uintptr_t)buf;
+ data.length = size;
+ shm_fd = tee_ioctl(fp, TEE_IOC_SHM_REGISTER, &data);
+ if (shm_fd < 0)
+ return -1;
+ *id = data.id;
+ return shm_fd;
+}
+
+TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *ctx)
+{
+ char devname[64];
+ struct file *fp;
+ size_t n;
+
+ if (!ctx)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ for (n = 0; n < TEEC_MAX_DEV_SEQ; n++) {
+ uint32_t gen_caps;
+
+ snprintf(devname, sizeof(devname), "/dev/tee%zu", n);
+ fp = teec_open_dev(devname, name, &gen_caps);
+ if (!IS_ERR(fp)) {
+ ctx->fp = fp;
+ ctx->reg_mem = gen_caps & TEE_GEN_CAP_REG_MEM;
+ return TEEC_SUCCESS;
+ }
+ }
+
+ return TEEC_ERROR_ITEM_NOT_FOUND;
+}
+
+void TEEC_FinalizeContext(TEEC_Context *ctx)
+{
+ if (ctx)
+ filp_close(ctx->fp, NULL);
+}
+
+TEEC_Result tee_open_session(TEEC_Context *ctx, TEEC_Session *sess, TEEC_UUID *uuid)
+{
+ TEEC_Result res;
+ uint32_t err_origin;
+
+ res = TEEC_InitializeContext(NULL, ctx);
+ if (res != TEEC_SUCCESS) {
+ pr_err("TEEC_InitializeContext failed with code 0x%x", res);
+ return res;
+ }
+
+ res = TEEC_OpenSession(ctx, sess, uuid,
+ TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
+ if (res != TEEC_SUCCESS) {
+ pr_err("TEEC_Opensession failed with code 0x%x origin 0x%x",
+ res, err_origin);
+ return res;
+ }
+
+ return TEEC_SUCCESS;
+}
+
+TEEC_Result tee_close_session(TEEC_Context *ctx, TEEC_Session *sess)
+{
+ TEEC_CloseSession(sess);
+ TEEC_FinalizeContext(ctx);
+
+ return TEEC_SUCCESS;
+}
+
+TEEC_UUID get_uuid_from_array(u32 a[])
+{
+ TEEC_UUID uuid;
+ int i = 0;
+
+ uuid.timeLow = a[0];
+ uuid.timeMid = a[1];
+ uuid.timeHiAndVersion = a[2];
+ for (i = 0; i < 8; i++)
+ uuid.clockSeqAndNode[i] = a[3+i];
+
+ return uuid;
+}
+
+
+TEEC_Result tee_invoke_cmd(TEEC_Session *sess, uint32_t cmd,
+ uint32_t paramTypes, TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT])
+{
+ TEEC_Operation op;
+ TEEC_Result res;
+ uint32_t err_origin;
+
+ memset(&op, 0, sizeof(op));
+
+ op.paramTypes = paramTypes;
+ memcpy(op.params, params, sizeof(TEEC_Parameter) * TEEC_CONFIG_PAYLOAD_REF_COUNT);
+
+ /*
+ * Prepare the argument. Pass a value in the first parameter,
+ * the remaining three parameters are unused.
+ */
+
+ /*
+ * TA_HELLO_WORLD_CMD_INC_VALUE is the actual function in the TA to be
+ * called.
+ */
+ res = TEEC_InvokeCommand(sess, cmd, &op, &err_origin);
+ if (res != TEEC_SUCCESS) {
+ pr_err("TEEC_InvokeCommand %d failed with code 0x%x origin 0x%x",
+ cmd, res, err_origin);
+ }
+ return res;
+}
+
+static TEEC_Result teec_pre_process_tmpref(TEEC_Context *ctx,
+ uint32_t param_type, TEEC_TempMemoryReference *tmpref,
+ struct tee_ioctl_param *param,
+ TEEC_SharedMemory *shm)
+{
+ TEEC_Result res;
+
+ switch (param_type) {
+ case TEEC_MEMREF_TEMP_INPUT:
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ shm->flags = TEEC_MEM_INPUT;
+ break;
+ case TEEC_MEMREF_TEMP_OUTPUT:
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ shm->flags = TEEC_MEM_OUTPUT;
+ break;
+ case TEEC_MEMREF_TEMP_INOUT:
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+ shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
+ break;
+ default:
+ return TEEC_ERROR_BAD_PARAMETERS;
+ }
+ shm->size = tmpref->size;
+
+ res = TEEC_AllocateSharedMemory(ctx, shm);
+ if (res != TEEC_SUCCESS)
+ return res;
+
+ memcpy(shm->buffer, tmpref->buffer, tmpref->size);
+ param->u.memref.size = tmpref->size;
+ param->u.memref.shm_id = shm->id;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result teec_pre_process_whole(
+ TEEC_RegisteredMemoryReference *memref,
+ struct tee_ioctl_param *param)
+{
+ const uint32_t inout = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
+ uint32_t flags = memref->parent->flags & inout;
+ TEEC_SharedMemory *shm;
+
+ if (flags == inout)
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+ else if (flags & TEEC_MEM_INPUT)
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ else if (flags & TEEC_MEM_OUTPUT)
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ else
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ shm = memref->parent;
+ /*
+ * We're using a shadow buffer in this reference, copy the real buffer
+ * into the shadow buffer if needed. We'll copy it back once we've
+ * returned from the call to secure world.
+ */
+ if (shm->shadow_buffer && (flags & TEEC_MEM_INPUT))
+ memcpy(shm->shadow_buffer, shm->buffer, shm->size);
+
+ param->u.memref.shm_id = shm->id;
+ param->u.memref.size = shm->size;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result teec_pre_process_partial(uint32_t param_type,
+ TEEC_RegisteredMemoryReference *memref,
+ struct tee_ioctl_param *param)
+{
+ uint32_t req_shm_flags;
+ TEEC_SharedMemory *shm;
+
+ switch (param_type) {
+ case TEEC_MEMREF_PARTIAL_INPUT:
+ req_shm_flags = TEEC_MEM_INPUT;
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ break;
+ case TEEC_MEMREF_PARTIAL_OUTPUT:
+ req_shm_flags = TEEC_MEM_OUTPUT;
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+ break;
+ case TEEC_MEMREF_PARTIAL_INOUT:
+ req_shm_flags = TEEC_MEM_OUTPUT | TEEC_MEM_INPUT;
+ param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+ break;
+ default:
+ return TEEC_ERROR_BAD_PARAMETERS;
+ }
+
+ shm = memref->parent;
+
+ if ((shm->flags & req_shm_flags) != req_shm_flags)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ /*
+ * We're using a shadow buffer in this reference, copy the real buffer
+ * into the shadow buffer if needed. We'll copy it back once we've
+ * returned from the call to secure world.
+ */
+ if (shm->shadow_buffer && param_type != TEEC_MEMREF_PARTIAL_OUTPUT)
+ memcpy((char *)shm->shadow_buffer + memref->offset,
+ (char *)shm->buffer + memref->offset, memref->size);
+
+ param->u.memref.shm_id = shm->id;
+ param->u.memref.shm_offs = memref->offset;
+ param->u.memref.size = memref->size;
+ return TEEC_SUCCESS;
+}
+
+static TEEC_Result teec_pre_process_operation(TEEC_Context *ctx,
+ TEEC_Operation *operation,
+ struct tee_ioctl_param *params,
+ TEEC_SharedMemory *shms)
+{
+ TEEC_Result res;
+ size_t n;
+
+ memset(shms, 0, sizeof(TEEC_SharedMemory) *
+ TEEC_CONFIG_PAYLOAD_REF_COUNT);
+ if (!operation) {
+ memset(params, 0, sizeof(struct tee_ioctl_param) *
+ TEEC_CONFIG_PAYLOAD_REF_COUNT);
+ return TEEC_SUCCESS;
+ }
+
+ for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) {
+ uint32_t param_type;
+
+ param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n);
+ switch (param_type) {
+ case TEEC_NONE:
+ params[n].attr = param_type;
+ break;
+ case TEEC_VALUE_INPUT:
+ case TEEC_VALUE_OUTPUT:
+ case TEEC_VALUE_INOUT:
+ params[n].attr = param_type;
+ params[n].u.value.a = operation->params[n].value.a;
+ params[n].u.value.b = operation->params[n].value.b;
+ break;
+ case TEEC_MEMREF_TEMP_INPUT:
+ case TEEC_MEMREF_TEMP_OUTPUT:
+ case TEEC_MEMREF_TEMP_INOUT:
+ res = teec_pre_process_tmpref(ctx, param_type,
+ &operation->params[n].tmpref, params + n,
+ shms + n);
+ if (res != TEEC_SUCCESS)
+ return res;
+ break;
+ case TEEC_MEMREF_WHOLE:
+ res = teec_pre_process_whole(
+ &operation->params[n].memref,
+ params + n);
+ if (res != TEEC_SUCCESS)
+ return res;
+ break;
+ case TEEC_MEMREF_PARTIAL_INPUT:
+ case TEEC_MEMREF_PARTIAL_OUTPUT:
+ case TEEC_MEMREF_PARTIAL_INOUT:
+ res = teec_pre_process_partial(param_type,
+ &operation->params[n].memref, params + n);
+ if (res != TEEC_SUCCESS)
+ return res;
+ break;
+ default:
+ return TEEC_ERROR_BAD_PARAMETERS;
+ }
+ }
+
+ return TEEC_SUCCESS;
+}
+
+static void teec_post_process_tmpref(uint32_t param_type,
+ TEEC_TempMemoryReference *tmpref,
+ struct tee_ioctl_param *param,
+ TEEC_SharedMemory *shm)
+{
+ if (param_type != TEEC_MEMREF_TEMP_INPUT) {
+ if (param->u.memref.size <= tmpref->size && tmpref->buffer)
+ memcpy(tmpref->buffer, shm->buffer,
+ param->u.memref.size);
+
+ tmpref->size = param->u.memref.size;
+ }
+}
+
+static void teec_post_process_whole(TEEC_RegisteredMemoryReference *memref,
+ struct tee_ioctl_param *param)
+{
+ TEEC_SharedMemory *shm = memref->parent;
+
+ if (shm->flags & TEEC_MEM_OUTPUT) {
+
+ /*
+ * We're using a shadow buffer in this reference, copy back
+ * the shadow buffer into the real buffer now that we've
+ * returned from secure world.
+ */
+ if (shm->shadow_buffer && param->u.memref.size <= shm->size)
+ memcpy(shm->buffer, shm->shadow_buffer,
+ param->u.memref.size);
+
+ memref->size = param->u.memref.size;
+ }
+}
+
+static void teec_post_process_partial(uint32_t param_type,
+ TEEC_RegisteredMemoryReference *memref,
+ struct tee_ioctl_param *param)
+{
+ if (param_type != TEEC_MEMREF_PARTIAL_INPUT) {
+ TEEC_SharedMemory *shm = memref->parent;
+
+ /*
+ * We're using a shadow buffer in this reference, copy back
+ * the shadow buffer into the real buffer now that we've
+ * returned from secure world.
+ */
+ if (shm->shadow_buffer && param->u.memref.size <= memref->size)
+ memcpy((char *)shm->buffer + memref->offset,
+ (char *)shm->shadow_buffer + memref->offset,
+ param->u.memref.size);
+
+ memref->size = param->u.memref.size;
+ }
+}
+
+static void teec_post_process_operation(TEEC_Operation *operation,
+ struct tee_ioctl_param *params,
+ TEEC_SharedMemory *shms)
+{
+ size_t n;
+
+ if (!operation)
+ return;
+
+ for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) {
+ uint32_t param_type;
+
+ param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n);
+ switch (param_type) {
+ case TEEC_VALUE_INPUT:
+ break;
+ case TEEC_VALUE_OUTPUT:
+ case TEEC_VALUE_INOUT:
+ operation->params[n].value.a = params[n].u.value.a;
+ operation->params[n].value.b = params[n].u.value.b;
+ break;
+ case TEEC_MEMREF_TEMP_INPUT:
+ case TEEC_MEMREF_TEMP_OUTPUT:
+ case TEEC_MEMREF_TEMP_INOUT:
+ teec_post_process_tmpref(param_type,
+ &operation->params[n].tmpref, params + n,
+ shms + n);
+ break;
+ case TEEC_MEMREF_WHOLE:
+ teec_post_process_whole(&operation->params[n].memref,
+ params + n);
+ break;
+ case TEEC_MEMREF_PARTIAL_INPUT:
+ case TEEC_MEMREF_PARTIAL_OUTPUT:
+ case TEEC_MEMREF_PARTIAL_INOUT:
+ teec_post_process_partial(param_type,
+ &operation->params[n].memref, params + n);
+ default:
+ break;
+ }
+ }
+}
+
+static void teec_free_temp_refs(TEEC_Operation *operation,
+ TEEC_SharedMemory *shms)
+{
+ size_t n;
+
+ if (!operation)
+ return;
+
+ for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) {
+ switch (TEEC_PARAM_TYPE_GET(operation->paramTypes, n)) {
+ case TEEC_MEMREF_TEMP_INPUT:
+ case TEEC_MEMREF_TEMP_OUTPUT:
+ case TEEC_MEMREF_TEMP_INOUT:
+ TEEC_ReleaseSharedMemory(shms + n);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static TEEC_Result ioctl_errno_to_res(int err)
+{
+ switch (err) {
+ case ENOMEM:
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ default:
+ return TEEC_ERROR_GENERIC;
+ }
+}
+
+static void uuid_to_octets(uint8_t d[TEE_IOCTL_UUID_LEN], const TEEC_UUID *s)
+{
+ d[0] = s->timeLow >> 24;
+ d[1] = s->timeLow >> 16;
+ d[2] = s->timeLow >> 8;
+ d[3] = s->timeLow;
+ d[4] = s->timeMid >> 8;
+ d[5] = s->timeMid;
+ d[6] = s->timeHiAndVersion >> 8;
+ d[7] = s->timeHiAndVersion;
+ memcpy(d + 8, s->clockSeqAndNode, sizeof(s->clockSeqAndNode));
+}
+
+TEEC_Result TEEC_OpenSession(TEEC_Context *ctx, TEEC_Session *session,
+ const TEEC_UUID *destination,
+ uint32_t connection_method, const void *connection_data,
+ TEEC_Operation *operation, uint32_t *ret_origin)
+{
+ uint64_t buf[(sizeof(struct tee_ioctl_open_session_arg) +
+ TEEC_CONFIG_PAYLOAD_REF_COUNT *
+ sizeof(struct tee_ioctl_param)) /
+ sizeof(uint64_t)] = { 0 };
+ struct tee_ioctl_buf_data buf_data;
+ struct tee_ioctl_open_session_arg *arg;
+ struct tee_ioctl_param *params;
+ TEEC_Result res;
+ uint32_t eorig;
+ TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+ int rc;
+
+ (void)&connection_data;
+
+ if (!ctx || !session) {
+ eorig = TEEC_ORIGIN_API;
+ res = TEEC_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ buf_data.buf_ptr = (uintptr_t)buf;
+ buf_data.buf_len = sizeof(buf);
+
+ arg = (struct tee_ioctl_open_session_arg *)buf;
+ arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT;
+ params = (struct tee_ioctl_param *)(arg + 1);
+
+ uuid_to_octets(arg->uuid, destination);
+ arg->clnt_login = connection_method;
+
+ res = teec_pre_process_operation(ctx, operation, params, shm);
+ if (res != TEEC_SUCCESS) {
+ eorig = TEEC_ORIGIN_API;
+ goto out_free_temp_refs;
+ }
+
+ rc = tee_ioctl(ctx->fp, TEE_IOC_OPEN_SESSION, &buf_data);
+ if (rc) {
+ EMSG("TEE_IOC_OPEN_SESSION failed");
+ eorig = TEEC_ORIGIN_COMMS;
+ res = ioctl_errno_to_res(rc);
+ goto out_free_temp_refs;
+ }
+ res = arg->ret;
+ eorig = arg->ret_origin;
+ if (res == TEEC_SUCCESS) {
+ session->ctx = ctx;
+ session->session_id = arg->session;
+ }
+ teec_post_process_operation(operation, params, shm);
+
+out_free_temp_refs:
+ teec_free_temp_refs(operation, shm);
+out:
+ if (ret_origin)
+ *ret_origin = eorig;
+ return res;
+}
+
+void TEEC_CloseSession(TEEC_Session *session)
+{
+ struct tee_ioctl_close_session_arg arg;
+
+ if (!session)
+ return;
+
+ arg.session = session->session_id;
+ if (tee_ioctl(session->ctx->fp, TEE_IOC_CLOSE_SESSION, &arg))
+ EMSG("Failed to close session 0x%x", session->session_id);
+}
+
+TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t cmd_id,
+ TEEC_Operation *operation, uint32_t *error_origin)
+{
+ uint64_t buf[(sizeof(struct tee_ioctl_invoke_arg) +
+ TEEC_CONFIG_PAYLOAD_REF_COUNT *
+ sizeof(struct tee_ioctl_param)) /
+ sizeof(uint64_t)] = { 0 };
+ struct tee_ioctl_buf_data buf_data;
+ struct tee_ioctl_invoke_arg *arg;
+ struct tee_ioctl_param *params;
+ TEEC_Result res;
+ uint32_t eorig;
+ TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+ int rc;
+
+ if (!session) {
+ eorig = TEEC_ORIGIN_API;
+ res = TEEC_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ buf_data.buf_ptr = (uintptr_t)buf;
+ buf_data.buf_len = sizeof(buf);
+
+ arg = (struct tee_ioctl_invoke_arg *)buf;
+ arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT;
+ params = (struct tee_ioctl_param *)(arg + 1);
+
+ arg->session = session->session_id;
+ arg->func = cmd_id;
+
+ if (operation) {
+ teec_mutex_lock(&teec_mutex);
+ operation->session = session;
+ teec_mutex_unlock(&teec_mutex);
+ }
+
+ res = teec_pre_process_operation(session->ctx, operation, params, shm);
+ if (res != TEEC_SUCCESS) {
+ eorig = TEEC_ORIGIN_API;
+ goto out_free_temp_refs;
+ }
+
+ rc = tee_ioctl(session->ctx->fp, TEE_IOC_INVOKE, &buf_data);
+ if (rc) {
+ EMSG("TEE_IOC_INVOKE failed");
+ eorig = TEEC_ORIGIN_COMMS;
+ res = ioctl_errno_to_res(rc);
+ goto out_free_temp_refs;
+ }
+
+ res = arg->ret;
+ eorig = arg->ret_origin;
+ teec_post_process_operation(operation, params, shm);
+
+out_free_temp_refs:
+ teec_free_temp_refs(operation, shm);
+out:
+ if (error_origin)
+ *error_origin = eorig;
+ return res;
+}
+
+void TEEC_RequestCancellation(TEEC_Operation *operation)
+{
+ struct tee_ioctl_cancel_arg arg;
+ TEEC_Session *session;
+ int ret;
+
+ if (!operation)
+ return;
+
+ teec_mutex_lock(&teec_mutex);
+ session = operation->session;
+ teec_mutex_unlock(&teec_mutex);
+
+ if (!session)
+ return;
+
+ arg.session = session->session_id;
+ arg.cancel_id = 0;
+
+ ret = tee_ioctl(session->ctx->fp, TEE_IOC_CANCEL, &arg);
+ if (ret)
+ EMSG("TEE_IOC_CANCEL: %d", ret);
+}
+
+TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm)
+{
+ int fd;
+ size_t s;
+
+ if (!ctx || !shm)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ s = shm->size;
+ if (!s)
+ s = 8;
+ if (ctx->reg_mem) {
+ fd = teec_shm_register(ctx->fp, shm->buffer, s, &shm->id);
+ if (fd < 0)
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ shm->registered_fd = fd;
+ shm->shadow_buffer = NULL;
+ } else {
+ fd = teec_shm_alloc(ctx->fp, s, &shm->id);
+ if (IS_ERR_OR_NULL((void *)fd))
+ return TEEC_ERROR_OUT_OF_MEMORY;
+
+ shm->shadow_buffer = (void *)fd;
+
+ if (shm->shadow_buffer == NULL) {
+ shm->id = -1;
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ }
+ shm->registered_fd = -1;
+ }
+
+ shm->alloced_size = s;
+ shm->buffer_allocated = false;
+ return TEEC_SUCCESS;
+}
+
+TEEC_Result TEEC_RegisterSharedMemoryFileDescriptor(TEEC_Context *ctx,
+ TEEC_SharedMemory *shm,
+ int fd)
+{
+ struct tee_ioctl_shm_register_fd_data data;
+ int rfd;
+
+ if (!ctx || !shm || fd < 0)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ memset(&data, 0, sizeof(data));
+ data.fd = fd;
+ rfd = tee_ioctl(ctx->fp, TEE_IOC_SHM_REGISTER_FD, &data);
+ if (rfd < 0)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ shm->buffer = NULL;
+ shm->shadow_buffer = NULL;
+ shm->registered_fd = rfd;
+ shm->id = data.id;
+ shm->size = data.size;
+ return TEEC_SUCCESS;
+}
+
+TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm)
+{
+ int fd;
+ size_t s;
+
+ if (!ctx || !shm)
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)))
+ return TEEC_ERROR_BAD_PARAMETERS;
+
+ s = shm->size;
+ if (!s)
+ s = 8;
+
+ if (ctx->reg_mem) {
+ shm->buffer = kmalloc(s, GFP_KERNEL);
+ if (!shm->buffer)
+ return TEEC_ERROR_OUT_OF_MEMORY;
+
+ fd = teec_shm_register(ctx->fp, shm->buffer, s, &shm->id);
+ if (fd < 0) {
+ kfree(shm->buffer);
+ shm->buffer = NULL;
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ }
+ shm->registered_fd = fd;
+ } else {
+ fd = teec_shm_alloc(ctx->fp, s, &shm->id);
+ if (IS_ERR_OR_NULL((void *)fd))
+ return TEEC_ERROR_OUT_OF_MEMORY;
+
+ shm->buffer = (void *)fd;
+
+ if (shm->buffer == NULL) {
+ shm->id = -1;
+ return TEEC_ERROR_OUT_OF_MEMORY;
+ }
+ shm->registered_fd = -1;
+ }
+
+ shm->shadow_buffer = NULL;
+ shm->alloced_size = s;
+ shm->buffer_allocated = true;
+ return TEEC_SUCCESS;
+}
+
+void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shm)
+{
+ if (!shm || shm->id == -1)
+ return;
+
+ else if (shm->buffer) {
+ if (shm->registered_fd >= 0) {
+ if (shm->buffer_allocated)
+ kfree(shm->buffer);
+ sys_close(shm->registered_fd);
+ }
+ } else if (shm->registered_fd >= 0) {
+ sys_close(shm->registered_fd);
+ }
+
+ shm->id = -1;
+ shm->shadow_buffer = NULL;
+ shm->buffer = NULL;
+ shm->registered_fd = -1;
+ shm->buffer_allocated = false;
+}
diff --git a/drivers/tee/tee_api/tee_client_api.h b/drivers/tee/tee_api/tee_client_api.h
new file mode 100644
index 00000000..bb6503b8
--- /dev/null
+++ b/drivers/tee/tee_api/tee_client_api.h
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * All rights reserved.
+ * Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TEE_CLIENT_API_H
+#define TEE_CLIENT_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// #include <linux/stdint.h>
+#include <linux/stddef.h>
+// #include <linux/stdbool.h>
+#include <linux/limits.h>
+#include <linux/fs.h>
+
+/*
+ * Defines the number of available memory references in an open session or
+ * invoke command operation payload.
+ */
+#define TEEC_CONFIG_PAYLOAD_REF_COUNT 4
+
+/**
+ * Defines the maximum size of a single shared memory block, in bytes, of both
+ * API allocated and API registered memory. There is no good value to put here
+ * (limits depend on specific config used), so this define does not provide any
+ * restriction in this implementation.
+ */
+#define TEEC_CONFIG_SHAREDMEM_MAX_SIZE ULONG_MAX
+
+/**
+ * Flag constants indicating the type of parameters encoded inside the
+ * operation payload (TEEC_Operation), Type is uint32_t.
+ *
+ * TEEC_NONE The Parameter is not used
+ *
+ * TEEC_VALUE_INPUT The Parameter is a TEEC_Value tagged as input.
+ *
+ * TEEC_VALUE_OUTPUT The Parameter is a TEEC_Value tagged as output.
+ *
+ * TEEC_VALUE_INOUT The Parameter is a TEEC_Value tagged as both as
+ * input and output, i.e., for which both the
+ * behaviors of TEEC_VALUE_INPUT and
+ * TEEC_VALUE_OUTPUT apply.
+ *
+ * TEEC_MEMREF_TEMP_INPUT The Parameter is a TEEC_TempMemoryReference
+ * describing a region of memory which needs to be
+ * temporarily registered for the duration of the
+ * Operation and is tagged as input.
+ *
+ * TEEC_MEMREF_TEMP_OUTPUT Same as TEEC_MEMREF_TEMP_INPUT, but the Memory
+ * Reference is tagged as output. The
+ * Implementation may update the size field to
+ * reflect the required output size in some use
+ * cases.
+ *
+ * TEEC_MEMREF_TEMP_INOUT A Temporary Memory Reference tagged as both
+ * input and output, i.e., for which both the
+ * behaviors of TEEC_MEMREF_TEMP_INPUT and
+ * TEEC_MEMREF_TEMP_OUTPUT apply.
+ *
+ * TEEC_MEMREF_WHOLE The Parameter is a Registered Memory Reference
+ * that refers to the entirety of its parent Shared
+ * Memory block. The parameter structure is a
+ * TEEC_MemoryReference. In this structure, the
+ * Implementation MUST read only the parent field
+ * and MAY update the size field when the operation
+ * completes.
+ *
+ * TEEC_MEMREF_PARTIAL_INPUT A Registered Memory Reference structure that
+ * refers to a partial region of its parent Shared
+ * Memory block and is tagged as input.
+ *
+ * TEEC_MEMREF_PARTIAL_OUTPUT Registered Memory Reference structure that
+ * refers to a partial region of its parent Shared
+ * Memory block and is tagged as output.
+ *
+ * TEEC_MEMREF_PARTIAL_INOUT The Registered Memory Reference structure that
+ * refers to a partial region of its parent Shared
+ * Memory block and is tagged as both input and
+ * output, i.e., for which both the behaviors of
+ * TEEC_MEMREF_PARTIAL_INPUT and
+ * TEEC_MEMREF_PARTIAL_OUTPUT apply.
+ */
+#define TEEC_NONE 0x00000000
+#define TEEC_VALUE_INPUT 0x00000001
+#define TEEC_VALUE_OUTPUT 0x00000002
+#define TEEC_VALUE_INOUT 0x00000003
+#define TEEC_MEMREF_TEMP_INPUT 0x00000005
+#define TEEC_MEMREF_TEMP_OUTPUT 0x00000006
+#define TEEC_MEMREF_TEMP_INOUT 0x00000007
+#define TEEC_MEMREF_WHOLE 0x0000000C
+#define TEEC_MEMREF_PARTIAL_INPUT 0x0000000D
+#define TEEC_MEMREF_PARTIAL_OUTPUT 0x0000000E
+#define TEEC_MEMREF_PARTIAL_INOUT 0x0000000F
+
+/**
+ * Flag constants indicating the data transfer direction of memory in
+ * TEEC_Parameter. TEEC_MEM_INPUT signifies data transfer direction from the
+ * client application to the TEE. TEEC_MEM_OUTPUT signifies data transfer
+ * direction from the TEE to the client application. Type is uint32_t.
+ *
+ * TEEC_MEM_INPUT The Shared Memory can carry data from the client
+ * application to the Trusted Application.
+ * TEEC_MEM_OUTPUT The Shared Memory can carry data from the Trusted
+ * Application to the client application.
+ */
+#define TEEC_MEM_INPUT 0x00000001
+#define TEEC_MEM_OUTPUT 0x00000002
+
+/**
+ * Return values. Type is TEEC_Result
+ *
+ * TEEC_SUCCESS The operation was successful.
+ * TEEC_ERROR_GENERIC Non-specific cause.
+ * TEEC_ERROR_ACCESS_DENIED Access privileges are not sufficient.
+ * TEEC_ERROR_CANCEL The operation was canceled.
+ * TEEC_ERROR_ACCESS_CONFLICT Concurrent accesses caused conflict.
+ * TEEC_ERROR_EXCESS_DATA Too much data for the requested operation was
+ * passed.
+ * TEEC_ERROR_BAD_FORMAT Input data was of invalid format.
+ * TEEC_ERROR_BAD_PARAMETERS Input parameters were invalid.
+ * TEEC_ERROR_BAD_STATE Operation is not valid in the current state.
+ * TEEC_ERROR_ITEM_NOT_FOUND The requested data item is not found.
+ * TEEC_ERROR_NOT_IMPLEMENTED The requested operation should exist but is not
+ * yet implemented.
+ * TEEC_ERROR_NOT_SUPPORTED The requested operation is valid but is not
+ * supported in this implementation.
+ * TEEC_ERROR_NO_DATA Expected data was missing.
+ * TEEC_ERROR_OUT_OF_MEMORY System ran out of resources.
+ * TEEC_ERROR_BUSY The system is busy working on something else.
+ * TEEC_ERROR_COMMUNICATION Communication with a remote party failed.
+ * TEEC_ERROR_SECURITY A security fault was detected.
+ * TEEC_ERROR_SHORT_BUFFER The supplied buffer is too short for the
+ * generated output.
+ * TEEC_ERROR_TARGET_DEAD Trusted Application has panicked
+ * during the operation.
+ */
+
+/**
+ * Standard defined error codes.
+ */
+#define TEEC_SUCCESS 0x00000000
+#define TEEC_ERROR_GENERIC 0xFFFF0000
+#define TEEC_ERROR_ACCESS_DENIED 0xFFFF0001
+#define TEEC_ERROR_CANCEL 0xFFFF0002
+#define TEEC_ERROR_ACCESS_CONFLICT 0xFFFF0003
+#define TEEC_ERROR_EXCESS_DATA 0xFFFF0004
+#define TEEC_ERROR_BAD_FORMAT 0xFFFF0005
+#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006
+#define TEEC_ERROR_BAD_STATE 0xFFFF0007
+#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008
+#define TEEC_ERROR_NOT_IMPLEMENTED 0xFFFF0009
+#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A
+#define TEEC_ERROR_NO_DATA 0xFFFF000B
+#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
+#define TEEC_ERROR_BUSY 0xFFFF000D
+#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
+#define TEEC_ERROR_SECURITY 0xFFFF000F
+#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
+#define TEEC_ERROR_EXTERNAL_CANCEL 0xFFFF0011
+#define TEEC_ERROR_TARGET_DEAD 0xFFFF3024
+
+/**
+ * Function error origins, of type TEEC_ErrorOrigin. These indicate where in
+ * the software stack a particular return value originates from.
+ *
+ * TEEC_ORIGIN_API The error originated within the TEE Client API
+ * implementation.
+ * TEEC_ORIGIN_COMMS The error originated within the underlying
+ * communications stack linking the rich OS with
+ * the TEE.
+ * TEEC_ORIGIN_TEE The error originated within the common TEE code.
+ * TEEC_ORIGIN_TRUSTED_APP The error originated within the Trusted Application
+ * code.
+ */
+#define TEEC_ORIGIN_API 0x00000001
+#define TEEC_ORIGIN_COMMS 0x00000002
+#define TEEC_ORIGIN_TEE 0x00000003
+#define TEEC_ORIGIN_TRUSTED_APP 0x00000004
+
+/**
+ * Session login methods, for use in TEEC_OpenSession() as parameter
+ * connectionMethod. Type is uint32_t.
+ *
+ * TEEC_LOGIN_PUBLIC No login data is provided.
+ * TEEC_LOGIN_USER Login data about the user running the Client
+ * Application process is provided.
+ * TEEC_LOGIN_GROUP Login data about the group running the Client
+ * Application process is provided.
+ * TEEC_LOGIN_APPLICATION Login data about the running Client Application
+ * itself is provided.
+ * TEEC_LOGIN_USER_APPLICATION Login data about the user and the running
+ * Client Application itself is provided.
+ * TEEC_LOGIN_GROUP_APPLICATION Login data about the group and the running
+ * Client Application itself is provided.
+ */
+#define TEEC_LOGIN_PUBLIC 0x00000000
+#define TEEC_LOGIN_USER 0x00000001
+#define TEEC_LOGIN_GROUP 0x00000002
+#define TEEC_LOGIN_APPLICATION 0x00000004
+#define TEEC_LOGIN_USER_APPLICATION 0x00000005
+#define TEEC_LOGIN_GROUP_APPLICATION 0x00000006
+
+/**
+ * Encode the paramTypes according to the supplied types.
+ *
+ * @param p0 The first param type.
+ * @param p1 The second param type.
+ * @param p2 The third param type.
+ * @param p3 The fourth param type.
+ */
+#define TEEC_PARAM_TYPES(p0, p1, p2, p3) \
+ ((p0) | ((p1) << 4) | ((p2) << 8) | ((p3) << 12))
+
+/**
+ * Get the i_th param type from the paramType.
+ *
+ * @param p The paramType.
+ * @param i The i-th parameter to get the type for.
+ */
+#define TEEC_PARAM_TYPE_GET(p, i) (((p) >> (i * 4)) & 0xF)
+
+typedef uint32_t TEEC_Result;
+
+/**
+ * struct TEEC_Context - Represents a connection between a client application
+ * and a TEE.
+ */
+typedef struct {
+ /* Implementation defined */
+ int fd;
+ struct file *fp;
+ bool reg_mem;
+} TEEC_Context;
+
+/**
+ * This type contains a Universally Unique Resource Identifier (UUID) type as
+ * defined in RFC4122. These UUID values are used to identify Trusted
+ * Applications.
+ */
+typedef struct {
+ uint32_t timeLow;
+ uint16_t timeMid;
+ uint16_t timeHiAndVersion;
+ uint8_t clockSeqAndNode[8];
+} TEEC_UUID;
+
+/**
+ * struct TEEC_SharedMemory - Memory to transfer data between a client
+ * application and trusted code.
+ *
+ * @param buffer The memory buffer which is to be, or has been, shared
+ * with the TEE.
+ * @param size The size, in bytes, of the memory buffer.
+ * @param flags Bit-vector which holds properties of buffer.
+ * The bit-vector can contain either or both of the
+ * TEEC_MEM_INPUT and TEEC_MEM_OUTPUT flags.
+ *
+ * A shared memory block is a region of memory allocated in the context of the
+ * client application memory space that can be used to transfer data between
+ * that client application and a trusted application. The user of this struct
+ * is responsible to populate the buffer pointer.
+ */
+typedef struct {
+ void *buffer;
+ size_t size;
+ uint32_t flags;
+ /*
+ * Implementation-Defined
+ */
+ int id;
+ size_t alloced_size;
+ void *shadow_buffer;
+ int registered_fd;
+ bool buffer_allocated;
+} TEEC_SharedMemory;
+
+/**
+ * struct TEEC_TempMemoryReference - Temporary memory to transfer data between
+ * a client application and trusted code, only used for the duration of the
+ * operation.
+ *
+ * @param buffer The memory buffer which is to be, or has been shared with
+ * the TEE.
+ * @param size The size, in bytes, of the memory buffer.
+ *
+ * A memory buffer that is registered temporarily for the duration of the
+ * operation to be called.
+ */
+typedef struct {
+ void *buffer;
+ size_t size;
+} TEEC_TempMemoryReference;
+
+/**
+ * struct TEEC_RegisteredMemoryReference - use a pre-registered or
+ * pre-allocated shared memory block of memory to transfer data between
+ * a client application and trusted code.
+ *
+ * @param parent Points to a shared memory structure. The memory reference
+ * may utilize the whole shared memory or only a part of it.
+ * Must not be NULL
+ *
+ * @param size The size, in bytes, of the memory buffer.
+ *
+ * @param offset The offset, in bytes, of the referenced memory region from
+ * the start of the shared memory block.
+ *
+ */
+typedef struct {
+ TEEC_SharedMemory *parent;
+ size_t size;
+ size_t offset;
+} TEEC_RegisteredMemoryReference;
+
+/**
+ * struct TEEC_Value - Small raw data container
+ *
+ * Instead of allocating a shared memory buffer this structure can be used
+ * to pass small raw data between a client application and trusted code.
+ *
+ * @param a The first integer value.
+ *
+ * @param b The second second value.
+ */
+typedef struct {
+ uint32_t a;
+ uint32_t b;
+} TEEC_Value;
+
+/**
+ * union TEEC_Parameter - Memory container to be used when passing data between
+ * client application and trusted code.
+ *
+ * Either the client uses a shared memory reference, parts of it or a small raw
+ * data container.
+ *
+ * @param tmpref A temporary memory reference only valid for the duration
+ * of the operation.
+ *
+ * @param memref The entire shared memory or parts of it.
+ *
+ * @param value The small raw data container to use
+ */
+typedef union {
+ TEEC_TempMemoryReference tmpref;
+ TEEC_RegisteredMemoryReference memref;
+ TEEC_Value value;
+} TEEC_Parameter;
+
+/**
+ * struct TEEC_Session - Represents a connection between a client application
+ * and a trusted application.
+ */
+typedef struct {
+ /* Implementation defined */
+ TEEC_Context *ctx;
+ uint32_t session_id;
+} TEEC_Session;
+
+/**
+ * struct TEEC_Operation - Holds information and memory references used in
+ * TEEC_InvokeCommand().
+ *
+ * @param started Client must initialize to zero if it needs to cancel
+ * an operation about to be performed.
+ * @param paramTypes Type of data passed. Use TEEC_PARAMS_TYPE macro to
+ * create the correct flags.
+ * 0 means TEEC_NONE is passed for all params.
+ * @param params Array of parameters of type TEEC_Parameter.
+ * @param session Internal pointer to the last session used by
+ * TEEC_InvokeCommand with this operation.
+ *
+ */
+typedef struct {
+ uint32_t started;
+ uint32_t paramTypes;
+ TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT];
+ /* Implementation-Defined */
+ TEEC_Session *session;
+} TEEC_Operation;
+
+/**
+ * TEEC_InitializeContext() - Initializes a context holding connection
+ * information on the specific TEE, designated by the name string.
+
+ * @param name A zero-terminated string identifying the TEE to connect to.
+ * If name is set to NULL, the default TEE is connected to. NULL
+ * is the only supported value in this version of the API
+ * implementation.
+ *
+ * @param context The context structure which is to be initialized.
+ *
+ * @return TEEC_SUCCESS The initialization was successful.
+ * @return TEEC_Result Something failed.
+ */
+TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context);
+
+/**
+ * TEEC_FinalizeContext() - Destroys a context holding connection information
+ * on the specific TEE.
+ *
+ * This function destroys an initialized TEE context, closing the connection
+ * between the client application and the TEE. This function must only be
+ * called when all sessions related to this TEE context have been closed and
+ * all shared memory blocks have been released.
+ *
+ * @param context The context to be destroyed.
+ */
+void TEEC_FinalizeContext(TEEC_Context *context);
+
+/**
+ * TEEC_OpenSession() - Opens a new session with the specified trusted
+ * application.
+ *
+ * @param context The initialized TEE context structure in which
+ * scope to open the session.
+ * @param session The session to initialize.
+ * @param destination A structure identifying the trusted application
+ * with which to open a session.
+ *
+ * @param connectionMethod The connection method to use.
+ * @param connectionData Any data necessary to connect with the chosen
+ * connection method. Not supported, should be set to
+ * NULL.
+ * @param operation An operation structure to use in the session. May
+ * be set to NULL to signify no operation structure
+ * needed.
+ *
+ * @param returnOrigin A parameter which will hold the error origin if
+ * this function returns any value other than
+ * TEEC_SUCCESS.
+ *
+ * @return TEEC_SUCCESS OpenSession successfully opened a new session.
+ * @return TEEC_Result Something failed.
+ *
+ */
+TEEC_Result TEEC_OpenSession(TEEC_Context *context,
+ TEEC_Session *session,
+ const TEEC_UUID *destination,
+ uint32_t connectionMethod,
+ const void *connectionData,
+ TEEC_Operation *operation,
+ uint32_t *returnOrigin);
+
+/**
+ * TEEC_CloseSession() - Closes the session which has been opened with the
+ * specific trusted application.
+ *
+ * @param session The opened session to close.
+ */
+void TEEC_CloseSession(TEEC_Session *session);
+
+/**
+ * TEEC_InvokeCommand() - Executes a command in the specified trusted
+ * application.
+ *
+ * @param session A handle to an open connection to the trusted
+ * application.
+ * @param commandID Identifier of the command in the trusted application
+ * to invoke.
+ * @param operation An operation structure to use in the invoke command.
+ * May be set to NULL to signify no operation structure
+ * needed.
+ * @param returnOrigin A parameter which will hold the error origin if this
+ * function returns any value other than TEEC_SUCCESS.
+ *
+ * @return TEEC_SUCCESS OpenSession successfully opened a new session.
+ * @return TEEC_Result Something failed.
+ */
+TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
+ uint32_t commandID,
+ TEEC_Operation *operation,
+ uint32_t *returnOrigin);
+
+/**
+ * TEEC_RegisterSharedMemory() - Register a block of existing memory as a
+ * shared block within the scope of the specified context.
+ *
+ * @param context The initialized TEE context structure in which scope to
+ * open the session.
+ * @param sharedMem pointer to the shared memory structure to register.
+ *
+ * @return TEEC_SUCCESS The registration was successful.
+ * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion.
+ * @return TEEC_Result Something failed.
+ */
+TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
+ TEEC_SharedMemory *sharedMem);
+
+/**
+ * TEEC_AllocateSharedMemory() - Allocate shared memory for TEE.
+ *
+ * @param context The initialized TEE context structure in which scope to
+ * open the session.
+ * @param sharedMem Pointer to the allocated shared memory.
+ *
+ * @return TEEC_SUCCESS The registration was successful.
+ * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion.
+ * @return TEEC_Result Something failed.
+ */
+TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
+ TEEC_SharedMemory *sharedMem);
+
+/**
+ * TEEC_ReleaseSharedMemory() - Free or deregister the shared memory.
+ *
+ * @param sharedMem Pointer to the shared memory to be freed.
+ */
+void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMemory);
+
+/**
+ * TEEC_RequestCancellation() - Request the cancellation of a pending open
+ * session or command invocation.
+ *
+ * @param operation Pointer to an operation previously passed to open session
+ * or invoke.
+ */
+void TEEC_RequestCancellation(TEEC_Operation *operation);
+
+TEEC_Result tee_open_session(TEEC_Context *ctx, TEEC_Session *sess, TEEC_UUID *uuid);
+
+TEEC_Result tee_close_session(TEEC_Context *ctx, TEEC_Session *sess);
+
+TEEC_UUID get_uuid_from_array(u32 a[]);
+
+TEEC_Result tee_invoke_cmd(TEEC_Session *sess, uint32_t cmd,
+ uint32_t paramTypes, TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/tee/tee_api/tee_kern.h b/drivers/tee/tee_api/tee_kern.h
new file mode 100644
index 00000000..f19b2b4c
--- /dev/null
+++ b/drivers/tee/tee_api/tee_kern.h
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEE_H
+#define __TEE_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/*
+ * This file describes the API provided by a TEE driver to user space.
+ *
+ * Each TEE driver defines a TEE specific protocol which is used for the
+ * data passed back and forth using TEE_IOC_CMD.
+ */
+
+/* Helpers to make the ioctl defines */
+#define TEE_IOC_MAGIC 0xa4
+#define TEE_IOC_BASE 0
+
+/* Flags relating to shared memory */
+#define TEE_IOCTL_SHM_MAPPED 0x1 /* memory mapped in normal world */
+#define TEE_IOCTL_SHM_DMA_BUF 0x2 /* dma-buf handle on shared memory */
+
+#define TEE_MAX_ARG_SIZE 1024
+
+#define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */
+#define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */
+
+/*
+ * TEE Implementation ID
+ */
+#define TEE_IMPL_ID_OPTEE 1
+
+/*
+ * OP-TEE specific capabilities
+ */
+#define TEE_OPTEE_CAP_TZ (1 << 0)
+
+/**
+ * struct tee_ioctl_version_data - TEE version
+ * @impl_id: [out] TEE implementation id
+ * @impl_caps: [out] Implementation specific capabilities
+ * @gen_caps: [out] Generic capabilities, defined by TEE_GEN_CAPS_* above
+ *
+ * Identifies the TEE implementation, @impl_id is one of TEE_IMPL_ID_* above.
+ * @impl_caps is implementation specific, for example TEE_OPTEE_CAP_*
+ * is valid when @impl_id == TEE_IMPL_ID_OPTEE.
+ */
+struct tee_ioctl_version_data {
+ __u32 impl_id;
+ __u32 impl_caps;
+ __u32 gen_caps;
+};
+
+/**
+ * TEE_IOC_VERSION - query version of TEE
+ *
+ * Takes a tee_ioctl_version_data struct and returns with the TEE version
+ * data filled in.
+ */
+#define TEE_IOC_VERSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 0, \
+ struct tee_ioctl_version_data)
+
+/**
+ * struct tee_ioctl_shm_alloc_data - Shared memory allocate argument
+ * @size: [in/out] Size of shared memory to allocate
+ * @flags: [in/out] Flags to/from allocation.
+ * @id: [out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_ALLOC below.
+ */
+struct tee_ioctl_shm_alloc_data {
+ __u64 size;
+ __u32 flags;
+ __s32 id;
+};
+
+/**
+ * TEE_IOC_SHM_ALLOC - allocate shared memory
+ *
+ * Allocates shared memory between the user space process and secure OS.
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The returned file descriptor is used to map the shared memory into user
+ * space. The shared memory is freed when the descriptor is closed and the
+ * memory is unmapped.
+ */
+#define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \
+ struct tee_ioctl_shm_alloc_data)
+
+/**
+ * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument
+ * @fd: [in] file descriptor identifying the shared memory
+ * @size: [out] Size of shared memory to allocate
+ * @flags: [in] Flags to/from allocation.
+ * @id: [out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_ALLOC below.
+ */
+struct tee_ioctl_shm_register_fd_data {
+ __s64 fd;
+ __u64 size;
+ __u32 flags;
+ __s32 id;
+} __aligned(8);
+
+/**
+ * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The returned file descriptor refers to the shared memory object in kernel
+ * land. The shared memory is freed when the descriptor is closed.
+ */
+#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \
+ struct tee_ioctl_shm_register_fd_data)
+
+/**
+ * struct tee_ioctl_shm_register_data - Shared memory register argument
+ * @addr: [in] Start address of shared memory to register
+ * @length: [in/out] Length of shared memory to register
+ * @flags: [in/out] Flags to/from registration.
+ * @id: [out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_REGISTER below.
+ */
+struct tee_ioctl_shm_register_data {
+ __u64 addr;
+ __u64 length;
+ __u32 flags;
+ __s32 id;
+};
+
+/**
+ * TEE_IOC_SHM_REGISTER - Register shared memory
+ *
+ * Registers shared memory between the user space process and secure OS.
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The shared memory is unregisterred when the descriptor is closed.
+ */
+#define TEE_IOC_SHM_REGISTER _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 9, \
+ struct tee_ioctl_shm_register_data)
+
+/**
+ * struct tee_ioctl_buf_data - Variable sized buffer
+ * @buf_ptr: [in] A __user pointer to a buffer
+ * @buf_len: [in] Length of the buffer above
+ *
+ * Used as argument for TEE_IOC_OPEN_SESSION, TEE_IOC_INVOKE,
+ * TEE_IOC_SUPPL_RECV, and TEE_IOC_SUPPL_SEND below.
+ */
+struct tee_ioctl_buf_data {
+ __u64 buf_ptr;
+ __u64 buf_len;
+};
+
+/*
+ * Attributes for struct tee_ioctl_param, selects field in the union
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_NONE 0 /* parameter not used */
+
+/*
+ * These defines value parameters (struct tee_ioctl_param_value)
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT 1
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT 3 /* input and output */
+
+/*
+ * These defines shared memory reference parameters (struct
+ * tee_ioctl_param_memref)
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT 5
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT 6
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT 7 /* input and output */
+
+/*
+ * Mask for the type part of the attribute, leaves room for more types
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff
+
+/* Meta parameter carrying extra information about the message. */
+#define TEE_IOCTL_PARAM_ATTR_META 0x100
+
+/* Mask of all known attr bits */
+#define TEE_IOCTL_PARAM_ATTR_MASK \
+ (TEE_IOCTL_PARAM_ATTR_TYPE_MASK | TEE_IOCTL_PARAM_ATTR_META)
+
+/*
+ * Matches TEEC_LOGIN_* in GP TEE Client API
+ * Are only defined for GP compliant TEEs
+ */
+#define TEE_IOCTL_LOGIN_PUBLIC 0
+#define TEE_IOCTL_LOGIN_USER 1
+#define TEE_IOCTL_LOGIN_GROUP 2
+#define TEE_IOCTL_LOGIN_APPLICATION 4
+#define TEE_IOCTL_LOGIN_USER_APPLICATION 5
+#define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6
+
+/**
+ * struct tee_ioctl_param_memref - memory reference
+ * @shm_offs: Offset into the shared memory object
+ * @size: Size of the buffer
+ * @shm_id: Shared memory identifier
+ *
+ * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an
+ * identifier representing the shared memory object. A memref can reference
+ * a part of a shared memory by specifying an offset (@shm_offs) and @size
+ * of the object. To supply the entire shared memory object set @shm_offs
+ * to 0 and @size to the previously returned size of the object.
+ */
+struct tee_ioctl_param_memref {
+ __u64 shm_offs;
+ __u64 size;
+ __s64 shm_id;
+};
+
+/**
+ * struct tee_ioctl_param_value - values
+ * @a: first value
+ * @b: second value
+ * @c: third value
+ *
+ * Value parameters are passed unchecked to the destination
+ */
+struct tee_ioctl_param_value {
+ __u64 a;
+ __u64 b;
+ __u64 c;
+};
+
+/**
+ * struct tee_ioctl_param - parameter
+ * @attr: attributes
+ * @memref: a memory reference
+ * @value: a value
+ *
+ * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in
+ * the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and
+ * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE
+ * indicates that none of the members are used.
+ */
+struct tee_ioctl_param {
+ __u64 attr;
+ union {
+ struct tee_ioctl_param_memref memref;
+ struct tee_ioctl_param_value value;
+ } u;
+};
+
+#define TEE_IOCTL_UUID_LEN 16
+
+/**
+ * struct tee_ioctl_open_session_arg - Open session argument
+ * @uuid: [in] UUID of the Trusted Application
+ * @clnt_uuid: [in] UUID of client
+ * @clnt_login: [in] Login class of client, TEE_IOCTL_LOGIN_* above
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @session: [out] Session id
+ * @ret: [out] return value
+ * @ret_origin [out] origin of the return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_ioctl_open_session_arg {
+ __u8 uuid[TEE_IOCTL_UUID_LEN];
+ __u8 clnt_uuid[TEE_IOCTL_UUID_LEN];
+ __u32 clnt_login;
+ __u32 cancel_id;
+ __u32 session;
+ __u32 ret;
+ __u32 ret_origin;
+ __u32 num_params;
+ /*
+ * this struct is 8 byte aligned since the 'struct tee_ioctl_param'
+ * which follows requires 8 byte alignment.
+ *
+ * Commented out element used to visualize the layout dynamic part
+ * of the struct. This field is not available at all if
+ * num_params == 0.
+ *
+ * struct tee_ioctl_param params[num_params];
+ */
+} __aligned(8);
+
+/**
+ * TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_ioctl_open_session_arg followed by any array of struct
+ * tee_ioctl_param
+ */
+#define TEE_IOC_OPEN_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 2, \
+ struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted
+ * Application
+ * @func: [in] Trusted Application function, specific to the TA
+ * @session: [in] Session id
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @ret: [out] return value
+ * @ret_origin [out] origin of the return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_ioctl_invoke_arg {
+ __u32 func;
+ __u32 session;
+ __u32 cancel_id;
+ __u32 ret;
+ __u32 ret_origin;
+ __u32 num_params;
+ /*
+ * this struct is 8 byte aligned since the 'struct tee_ioctl_param'
+ * which follows requires 8 byte alignment.
+ *
+ * Commented out element used to visualize the layout dynamic part
+ * of the struct. This field is not available at all if
+ * num_params == 0.
+ *
+ * struct tee_ioctl_param params[num_params];
+ */
+} __aligned(8);
+
+/**
+ * TEE_IOC_INVOKE - Invokes a function in a Trusted Application
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_invoke_func_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_INVOKE _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 3, \
+ struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_ioctl_cancel_arg - Cancels an open session or invoke ioctl
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @session: [in] Session id, if the session is opened, else set to 0
+ */
+struct tee_ioctl_cancel_arg {
+ __u32 cancel_id;
+ __u32 session;
+};
+
+/**
+ * TEE_IOC_CANCEL - Cancels an open session or invoke
+ */
+#define TEE_IOC_CANCEL _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 4, \
+ struct tee_ioctl_cancel_arg)
+
+/**
+ * struct tee_ioctl_close_session_arg - Closes an open session
+ * @session: [in] Session id
+ */
+struct tee_ioctl_close_session_arg {
+ __u32 session;
+};
+
+/**
+ * TEE_IOC_CLOSE_SESSION - Closes a session
+ */
+#define TEE_IOC_CLOSE_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 5, \
+ struct tee_ioctl_close_session_arg)
+
+/**
+ * struct tee_iocl_supp_recv_arg - Receive a request for a supplicant function
+ * @func: [in] supplicant function
+ * @num_params [in/out] number of parameters following this struct
+ *
+ * @num_params is the number of params that tee-supplicant has room to
+ * receive when input, @num_params is the number of actual params
+ * tee-supplicant receives when output.
+ */
+struct tee_iocl_supp_recv_arg {
+ __u32 func;
+ __u32 num_params;
+ /*
+ * this struct is 8 byte aligned since the 'struct tee_ioctl_param'
+ * which follows requires 8 byte alignment.
+ *
+ * Commented out element used to visualize the layout dynamic part
+ * of the struct. This field is not available at all if
+ * num_params == 0.
+ *
+ * struct tee_ioctl_param params[num_params];
+ */
+} __aligned(8);
+
+/**
+ * TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_iocl_supp_recv_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_SUPPL_RECV _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 6, \
+ struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_iocl_supp_send_arg - Send a response to a received request
+ * @ret: [out] return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_iocl_supp_send_arg {
+ __u32 ret;
+ __u32 num_params;
+ /*
+ * this struct is 8 byte aligned since the 'struct tee_ioctl_param'
+ * which follows requires 8 byte alignment.
+ *
+ * Commented out element used to visualize the layout dynamic part
+ * of the struct. This field is not available at all if
+ * num_params == 0.
+ *
+ * struct tee_ioctl_param params[num_params];
+ */
+} __aligned(8);
+/**
+ * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_iocl_supp_send_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \
+ struct tee_ioctl_buf_data)
+
+/*
+ * Five syscalls are used when communicating with the TEE driver.
+ * open(): opens the device associated with the driver
+ * ioctl(): as described above operating on the file descriptor from open()
+ * close(): two cases
+ * - closes the device file descriptor
+ * - closes a file descriptor connected to allocated shared memory
+ * mmap(): maps shared memory into user space using information from struct
+ * tee_ioctl_shm_alloc_data
+ * munmap(): unmaps previously shared memory
+ */
+
+#endif /*__TEE_H*/
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
new file mode 100644
index 00000000..2b60b62f
--- /dev/null
+++ b/drivers/tee/tee_core.c
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include <linux/uaccess.h>
+#include "tee_private.h"
+
+#define TEE_NUM_DEVICES 32
+
+#define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x))
+
+/*
+ * Unprivileged devices in the lower half range and privileged devices in
+ * the upper half range.
+ */
+static DECLARE_BITMAP(dev_mask, TEE_NUM_DEVICES);
+static DEFINE_SPINLOCK(driver_lock);
+
+static struct class *tee_class;
+static dev_t tee_devt;
+
+static struct tee_context *teedev_open(struct tee_device *teedev)
+{
+ int rc;
+ struct tee_context *ctx;
+
+ if (!tee_device_get(teedev))
+ return ERR_PTR(-EINVAL);
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ kref_init(&ctx->refcount);
+ ctx->teedev = teedev;
+ INIT_LIST_HEAD(&ctx->list_shm);
+ rc = teedev->desc->ops->open(ctx);
+ if (rc)
+ goto err;
+
+ return ctx;
+err:
+ kfree(ctx);
+ tee_device_put(teedev);
+ return ERR_PTR(rc);
+
+}
+
+void teedev_ctx_get(struct tee_context *ctx)
+{
+ if (ctx->releasing)
+ return;
+
+ kref_get(&ctx->refcount);
+}
+
+static void teedev_ctx_release(struct kref *ref)
+{
+ struct tee_context *ctx = container_of(ref, struct tee_context,
+ refcount);
+ ctx->releasing = true;
+ ctx->teedev->desc->ops->release(ctx);
+ kfree(ctx);
+}
+
+void teedev_ctx_put(struct tee_context *ctx)
+{
+ if (ctx->releasing)
+ return;
+
+ kref_put(&ctx->refcount, teedev_ctx_release);
+}
+
+static void teedev_close_context(struct tee_context *ctx)
+{
+ tee_device_put(ctx->teedev);
+ teedev_ctx_put(ctx);
+}
+
+static int tee_open(struct inode *inode, struct file *filp)
+{
+ struct tee_context *ctx;
+
+ ctx = teedev_open(container_of(inode->i_cdev, struct tee_device, cdev));
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+
+ filp->private_data = ctx;
+ return 0;
+}
+
+static int tee_release(struct inode *inode, struct file *filp)
+{
+ teedev_close_context(filp->private_data);
+ return 0;
+}
+
+static int tee_ioctl_version(struct tee_context *ctx,
+ struct tee_ioctl_version_data __user *uvers)
+{
+ struct tee_ioctl_version_data vers;
+
+ ctx->teedev->desc->ops->get_version(ctx->teedev, &vers);
+
+ if (ctx->teedev->desc->flags & TEE_DESC_PRIVILEGED)
+ vers.gen_caps |= TEE_GEN_CAP_PRIVILEGED;
+
+ if (copy_to_user(uvers, &vers, sizeof(vers)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int tee_ioctl_shm_alloc(struct tee_context *ctx,
+ struct tee_ioctl_shm_alloc_data __user *udata)
+{
+ long ret;
+ struct tee_ioctl_shm_alloc_data data;
+ struct tee_shm *shm;
+
+ if (copy_from_user(&data, udata, sizeof(data)))
+ return -EFAULT;
+
+ /* Currently no input flags are supported */
+ if (data.flags)
+ return -EINVAL;
+
+ shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ data.id = shm->id;
+ data.flags = shm->flags;
+ data.size = shm->size;
+
+ if (copy_to_user(udata, &data, sizeof(data)))
+ ret = -EFAULT;
+ else
+ ret = tee_shm_get_fd(shm);
+
+ /*
+ * When user space closes the file descriptor the shared memory
+ * should be freed or if tee_shm_get_fd() failed then it will
+ * be freed immediately.
+ */
+ tee_shm_put(shm);
+ return ret;
+}
+
+static int
+tee_ioctl_shm_register(struct tee_context *ctx,
+ struct tee_ioctl_shm_register_data __user *udata)
+{
+ long ret;
+ struct tee_ioctl_shm_register_data data;
+ struct tee_shm *shm;
+
+ if (copy_from_user(&data, udata, sizeof(data)))
+ return -EFAULT;
+
+ /* Currently no input flags are supported */
+ if (data.flags)
+ return -EINVAL;
+
+ shm = tee_shm_register(ctx, data.addr, data.length,
+ TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ data.id = shm->id;
+ data.flags = shm->flags;
+ data.length = shm->size;
+
+ if (copy_to_user(udata, &data, sizeof(data)))
+ ret = -EFAULT;
+ else
+ ret = tee_shm_get_fd(shm);
+ /*
+ * When user space closes the file descriptor the shared memory
+ * should be freed or if tee_shm_get_fd() failed then it will
+ * be freed immediately.
+ */
+ tee_shm_put(shm);
+ return ret;
+}
+
+static int tee_ioctl_shm_register_fd(struct tee_context *ctx,
+ struct tee_ioctl_shm_register_fd_data __user *udata)
+{
+ struct tee_ioctl_shm_register_fd_data data;
+ struct tee_shm *shm;
+ long ret;
+
+ if (copy_from_user(&data, udata, sizeof(data)))
+ return -EFAULT;
+
+ /* Currently no input flags are supported */
+ if (data.flags)
+ return -EINVAL;
+
+ shm = tee_shm_register_fd(ctx, data.fd);
+ if (IS_ERR_OR_NULL(shm))
+ return -EINVAL;
+
+ data.id = shm->id;
+ data.flags = shm->flags;
+ data.size = shm->size;
+
+ if (copy_to_user(udata, &data, sizeof(data)))
+ ret = -EFAULT;
+ else
+ ret = tee_shm_get_fd(shm);
+
+ /*
+ * When user space closes the file descriptor the shared memory
+ * should be freed or if tee_shm_get_fd() failed then it will
+ * be freed immediately.
+ */
+ tee_shm_put(shm);
+ return ret;
+}
+
+static int params_from_user(struct tee_context *ctx, struct tee_param *params,
+ size_t num_params,
+ struct tee_ioctl_param __user *uparams)
+{
+ size_t n;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_shm *shm;
+ struct tee_ioctl_param ip;
+
+ if (copy_from_user(&ip, uparams + n, sizeof(ip)))
+ return -EFAULT;
+
+ /* All unused attribute bits has to be zero */
+ if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_MASK)
+ return -EINVAL;
+
+ params[n].attr = ip.attr;
+ switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ params[n].u.value.a = ip.a;
+ params[n].u.value.b = ip.b;
+ params[n].u.value.c = ip.c;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ /*
+ * If we fail to get a pointer to a shared memory
+ * object (and increase the ref count) from an
+ * identifier we return an error. All pointers that
+ * has been added in params have an increased ref
+ * count. It's the callers responibility to do
+ * tee_shm_put() on all resolved pointers.
+ */
+ shm = tee_shm_get_from_id(ctx, ip.c);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ /*
+ * Ensure offset + size does not overflow offset
+ * and does not overflow the size of the referred
+ * shared memory object.
+ */
+ if ((ip.a + ip.b) < ip.a ||
+ (ip.a + ip.b) > shm->size) {
+ tee_shm_put(shm);
+ return -EINVAL;
+ }
+
+ params[n].u.memref.shm_offs = ip.a;
+ params[n].u.memref.size = ip.b;
+ params[n].u.memref.shm = shm;
+ break;
+ default:
+ /* Unknown attribute */
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int params_to_user(struct tee_ioctl_param __user *uparams,
+ size_t num_params, struct tee_param *params)
+{
+ size_t n;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_ioctl_param __user *up = uparams + n;
+ struct tee_param *p = params + n;
+
+ switch (p->attr) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ if (put_user(p->u.value.a, &up->a) ||
+ put_user(p->u.value.b, &up->b) ||
+ put_user(p->u.value.c, &up->c))
+ return -EFAULT;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ if (put_user((u64)p->u.memref.size, &up->b))
+ return -EFAULT;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static int tee_ioctl_open_session(struct tee_context *ctx,
+ struct tee_ioctl_buf_data __user *ubuf)
+{
+ int rc;
+ size_t n;
+ struct tee_ioctl_buf_data buf;
+ struct tee_ioctl_open_session_arg __user *uarg;
+ struct tee_ioctl_open_session_arg arg;
+ struct tee_ioctl_param __user *uparams = NULL;
+ struct tee_param *params = NULL;
+ bool have_session = false;
+
+ if (!ctx->teedev->desc->ops->open_session)
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, sizeof(buf)))
+ return -EFAULT;
+
+ if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+ buf.buf_len < sizeof(struct tee_ioctl_open_session_arg))
+ return -EINVAL;
+
+ uarg = u64_to_user_ptr(buf.buf_ptr);
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+ return -EFAULT;
+
+ if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
+ return -EINVAL;
+
+ if (arg.num_params) {
+ params = kcalloc(arg.num_params, sizeof(struct tee_param),
+ GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ uparams = uarg->params;
+ rc = params_from_user(ctx, params, arg.num_params, uparams);
+ if (rc)
+ goto out;
+ }
+
+ rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params);
+ if (rc)
+ goto out;
+ have_session = true;
+
+ if (put_user(arg.session, &uarg->session) ||
+ put_user(arg.ret, &uarg->ret) ||
+ put_user(arg.ret_origin, &uarg->ret_origin)) {
+ rc = -EFAULT;
+ goto out;
+ }
+ rc = params_to_user(uparams, arg.num_params, params);
+out:
+ /*
+ * If we've succeeded to open the session but failed to communicate
+ * it back to user space, close the session again to avoid leakage.
+ */
+ if (rc && have_session && ctx->teedev->desc->ops->close_session)
+ ctx->teedev->desc->ops->close_session(ctx, arg.session);
+
+ if (params) {
+ /* Decrease ref count for all valid shared memory pointers */
+ for (n = 0; n < arg.num_params; n++)
+ if (tee_param_is_memref(params + n) &&
+ params[n].u.memref.shm)
+ tee_shm_put(params[n].u.memref.shm);
+ kfree(params);
+ }
+
+ return rc;
+}
+
+static int tee_ioctl_invoke(struct tee_context *ctx,
+ struct tee_ioctl_buf_data __user *ubuf)
+{
+ int rc;
+ size_t n;
+ struct tee_ioctl_buf_data buf;
+ struct tee_ioctl_invoke_arg __user *uarg;
+ struct tee_ioctl_invoke_arg arg;
+ struct tee_ioctl_param __user *uparams = NULL;
+ struct tee_param *params = NULL;
+
+ if (!ctx->teedev->desc->ops->invoke_func)
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, sizeof(buf)))
+ return -EFAULT;
+
+ if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+ buf.buf_len < sizeof(struct tee_ioctl_invoke_arg))
+ return -EINVAL;
+
+ uarg = u64_to_user_ptr(buf.buf_ptr);
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+ return -EFAULT;
+
+ if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
+ return -EINVAL;
+
+ if (arg.num_params) {
+ params = kcalloc(arg.num_params, sizeof(struct tee_param),
+ GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ uparams = uarg->params;
+ rc = params_from_user(ctx, params, arg.num_params, uparams);
+ if (rc)
+ goto out;
+ }
+
+ rc = ctx->teedev->desc->ops->invoke_func(ctx, &arg, params);
+ if (rc)
+ goto out;
+
+ if (put_user(arg.ret, &uarg->ret) ||
+ put_user(arg.ret_origin, &uarg->ret_origin)) {
+ rc = -EFAULT;
+ goto out;
+ }
+ rc = params_to_user(uparams, arg.num_params, params);
+out:
+ if (params) {
+ /* Decrease ref count for all valid shared memory pointers */
+ for (n = 0; n < arg.num_params; n++)
+ if (tee_param_is_memref(params + n) &&
+ params[n].u.memref.shm)
+ tee_shm_put(params[n].u.memref.shm);
+ kfree(params);
+ }
+ return rc;
+}
+
+static int tee_ioctl_cancel(struct tee_context *ctx,
+ struct tee_ioctl_cancel_arg __user *uarg)
+{
+ struct tee_ioctl_cancel_arg arg;
+
+ if (!ctx->teedev->desc->ops->cancel_req)
+ return -EINVAL;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+ return -EFAULT;
+
+ return ctx->teedev->desc->ops->cancel_req(ctx, arg.cancel_id,
+ arg.session);
+}
+
+static int
+tee_ioctl_close_session(struct tee_context *ctx,
+ struct tee_ioctl_close_session_arg __user *uarg)
+{
+ struct tee_ioctl_close_session_arg arg;
+
+ if (!ctx->teedev->desc->ops->close_session)
+ return -EINVAL;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+ return -EFAULT;
+
+ return ctx->teedev->desc->ops->close_session(ctx, arg.session);
+}
+
+static int params_to_supp(struct tee_context *ctx,
+ struct tee_ioctl_param __user *uparams,
+ size_t num_params, struct tee_param *params)
+{
+ size_t n;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_ioctl_param ip;
+ struct tee_param *p = params + n;
+
+ ip.attr = p->attr;
+ switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ ip.a = p->u.value.a;
+ ip.b = p->u.value.b;
+ ip.c = p->u.value.c;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ ip.b = p->u.memref.size;
+ if (!p->u.memref.shm) {
+ ip.a = 0;
+ ip.c = (u64)-1; /* invalid shm id */
+ break;
+ }
+ ip.a = p->u.memref.shm_offs;
+ ip.c = p->u.memref.shm->id;
+ break;
+ default:
+ ip.a = 0;
+ ip.b = 0;
+ ip.c = 0;
+ break;
+ }
+
+ if (copy_to_user(uparams + n, &ip, sizeof(ip)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int tee_ioctl_supp_recv(struct tee_context *ctx,
+ struct tee_ioctl_buf_data __user *ubuf)
+{
+ int rc;
+ struct tee_ioctl_buf_data buf;
+ struct tee_iocl_supp_recv_arg __user *uarg;
+ struct tee_param *params;
+ u32 num_params;
+ u32 func;
+
+ if (!ctx->teedev->desc->ops->supp_recv)
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, sizeof(buf)))
+ return -EFAULT;
+
+ if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+ buf.buf_len < sizeof(struct tee_iocl_supp_recv_arg))
+ return -EINVAL;
+
+ uarg = u64_to_user_ptr(buf.buf_ptr);
+ if (get_user(num_params, &uarg->num_params))
+ return -EFAULT;
+
+ if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) != buf.buf_len)
+ return -EINVAL;
+
+ params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+
+ rc = params_from_user(ctx, params, num_params, uarg->params);
+ if (rc)
+ goto out;
+
+ rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params);
+ if (rc)
+ goto out;
+
+ if (put_user(func, &uarg->func) ||
+ put_user(num_params, &uarg->num_params)) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ rc = params_to_supp(ctx, uarg->params, num_params, params);
+out:
+ kfree(params);
+ return rc;
+}
+
+static int params_from_supp(struct tee_param *params, size_t num_params,
+ struct tee_ioctl_param __user *uparams)
+{
+ size_t n;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_param *p = params + n;
+ struct tee_ioctl_param ip;
+
+ if (copy_from_user(&ip, uparams + n, sizeof(ip)))
+ return -EFAULT;
+
+ /* All unused attribute bits has to be zero */
+ if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_MASK)
+ return -EINVAL;
+
+ p->attr = ip.attr;
+ switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ /* Only out and in/out values can be updated */
+ p->u.value.a = ip.a;
+ p->u.value.b = ip.b;
+ p->u.value.c = ip.c;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ /*
+ * Only the size of the memref can be updated.
+ * Since we don't have access to the original
+ * parameters here, only store the supplied size.
+ * The driver will copy the updated size into the
+ * original parameters.
+ */
+ p->u.memref.shm = NULL;
+ p->u.memref.shm_offs = 0;
+ p->u.memref.size = ip.b;
+ break;
+ default:
+ memset(&p->u, 0, sizeof(p->u));
+ break;
+ }
+ }
+ return 0;
+}
+
+static int tee_ioctl_supp_send(struct tee_context *ctx,
+ struct tee_ioctl_buf_data __user *ubuf)
+{
+ long rc;
+ struct tee_ioctl_buf_data buf;
+ struct tee_iocl_supp_send_arg __user *uarg;
+ struct tee_param *params;
+ u32 num_params;
+ u32 ret;
+
+ /* Not valid for this driver */
+ if (!ctx->teedev->desc->ops->supp_send)
+ return -EINVAL;
+
+ if (copy_from_user(&buf, ubuf, sizeof(buf)))
+ return -EFAULT;
+
+ if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+ buf.buf_len < sizeof(struct tee_iocl_supp_send_arg))
+ return -EINVAL;
+
+ uarg = u64_to_user_ptr(buf.buf_ptr);
+ if (get_user(ret, &uarg->ret) ||
+ get_user(num_params, &uarg->num_params))
+ return -EFAULT;
+
+ if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) > buf.buf_len)
+ return -EINVAL;
+
+ params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+
+ rc = params_from_supp(params, num_params, uarg->params);
+ if (rc)
+ goto out;
+
+ rc = ctx->teedev->desc->ops->supp_send(ctx, ret, num_params, params);
+out:
+ kfree(params);
+ return rc;
+}
+
+static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct tee_context *ctx = filp->private_data;
+ void __user *uarg = (void __user *)arg;
+
+ switch (cmd) {
+ case TEE_IOC_VERSION:
+ return tee_ioctl_version(ctx, uarg);
+ case TEE_IOC_SHM_ALLOC:
+ return tee_ioctl_shm_alloc(ctx, uarg);
+ case TEE_IOC_SHM_REGISTER:
+ return tee_ioctl_shm_register(ctx, uarg);
+ case TEE_IOC_SHM_REGISTER_FD:
+ return tee_ioctl_shm_register_fd(ctx, uarg);
+ case TEE_IOC_OPEN_SESSION:
+ return tee_ioctl_open_session(ctx, uarg);
+ case TEE_IOC_INVOKE:
+ return tee_ioctl_invoke(ctx, uarg);
+ case TEE_IOC_CANCEL:
+ return tee_ioctl_cancel(ctx, uarg);
+ case TEE_IOC_CLOSE_SESSION:
+ return tee_ioctl_close_session(ctx, uarg);
+ case TEE_IOC_SUPPL_RECV:
+ return tee_ioctl_supp_recv(ctx, uarg);
+ case TEE_IOC_SUPPL_SEND:
+ return tee_ioctl_supp_send(ctx, uarg);
+ default:
+ return -EINVAL;
+ }
+}
+
+#include "tee_core_kern_api.h"
+
+static const struct file_operations tee_fops = {
+ .owner = THIS_MODULE,
+ .open = tee_open,
+ .release = tee_release,
+ .unlocked_ioctl = tee_ioctl,
+ .compat_ioctl = tee_ioctl,
+};
+
+static void tee_release_device(struct device *dev)
+{
+ struct tee_device *teedev = container_of(dev, struct tee_device, dev);
+
+ spin_lock(&driver_lock);
+ clear_bit(teedev->id, dev_mask);
+ spin_unlock(&driver_lock);
+ mutex_destroy(&teedev->mutex);
+ idr_destroy(&teedev->idr);
+ kfree(teedev);
+}
+
+/**
+ * tee_device_alloc() - Allocate a new struct tee_device instance
+ * @teedesc: Descriptor for this driver
+ * @dev: Parent device for this device
+ * @pool: Shared memory pool, NULL if not used
+ * @driver_data: Private driver data for this device
+ *
+ * Allocates a new struct tee_device instance. The device is
+ * removed by tee_device_unregister().
+ *
+ * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure
+ */
+struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
+ struct device *dev,
+ struct tee_shm_pool *pool,
+ void *driver_data)
+{
+ struct tee_device *teedev;
+ void *ret;
+ int rc, max_id;
+ int offs = 0;
+
+ if (!teedesc || !teedesc->name || !teedesc->ops ||
+ !teedesc->ops->get_version || !teedesc->ops->open ||
+ !teedesc->ops->release || !pool)
+ return ERR_PTR(-EINVAL);
+
+ teedev = kzalloc(sizeof(*teedev), GFP_KERNEL);
+ if (!teedev) {
+ ret = ERR_PTR(-ENOMEM);
+ goto err;
+ }
+
+ max_id = TEE_NUM_DEVICES / 2;
+
+ if (teedesc->flags & TEE_DESC_PRIVILEGED) {
+ offs = TEE_NUM_DEVICES / 2;
+ max_id = TEE_NUM_DEVICES;
+ }
+
+ spin_lock(&driver_lock);
+ teedev->id = find_next_zero_bit(dev_mask, max_id, offs);
+ if (teedev->id < max_id)
+ set_bit(teedev->id, dev_mask);
+ spin_unlock(&driver_lock);
+
+ if (teedev->id >= max_id) {
+ ret = ERR_PTR(-ENOMEM);
+ goto err;
+ }
+
+ snprintf(teedev->name, sizeof(teedev->name), "tee%s%d",
+ teedesc->flags & TEE_DESC_PRIVILEGED ? "priv" : "",
+ teedev->id - offs);
+
+ teedev->dev.class = tee_class;
+ teedev->dev.release = tee_release_device;
+ teedev->dev.parent = dev;
+
+ teedev->dev.devt = MKDEV(MAJOR(tee_devt), teedev->id);
+
+ rc = dev_set_name(&teedev->dev, "%s", teedev->name);
+ if (rc) {
+ ret = ERR_PTR(rc);
+ goto err_devt;
+ }
+
+ cdev_init(&teedev->cdev, &tee_fops);
+ teedev->cdev.owner = teedesc->owner;
+ teedev->cdev.kobj.parent = &teedev->dev.kobj;
+
+ dev_set_drvdata(&teedev->dev, driver_data);
+ device_initialize(&teedev->dev);
+
+ /* 1 as tee_device_unregister() does one final tee_device_put() */
+ teedev->num_users = 1;
+ init_completion(&teedev->c_no_users);
+ mutex_init(&teedev->mutex);
+ idr_init(&teedev->idr);
+
+ teedev->desc = teedesc;
+ teedev->pool = pool;
+
+ return teedev;
+err_devt:
+ unregister_chrdev_region(teedev->dev.devt, 1);
+err:
+ pr_err("could not register %s driver\n",
+ teedesc->flags & TEE_DESC_PRIVILEGED ? "privileged" : "client");
+ if (teedev && teedev->id < TEE_NUM_DEVICES) {
+ spin_lock(&driver_lock);
+ clear_bit(teedev->id, dev_mask);
+ spin_unlock(&driver_lock);
+ }
+ kfree(teedev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tee_device_alloc);
+
+static ssize_t implementation_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tee_device *teedev = container_of(dev, struct tee_device, dev);
+ struct tee_ioctl_version_data vers;
+
+ teedev->desc->ops->get_version(teedev, &vers);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", vers.impl_id);
+}
+static DEVICE_ATTR_RO(implementation_id);
+
+static struct attribute *tee_dev_attrs[] = {
+ &dev_attr_implementation_id.attr,
+ NULL
+};
+
+static const struct attribute_group tee_dev_group = {
+ .attrs = tee_dev_attrs,
+};
+
+/**
+ * tee_device_register() - Registers a TEE device
+ * @teedev: Device to register
+ *
+ * tee_device_unregister() need to be called to remove the @teedev if
+ * this function fails.
+ *
+ * @returns < 0 on failure
+ */
+int tee_device_register(struct tee_device *teedev)
+{
+ int rc;
+
+ if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) {
+ dev_err(&teedev->dev, "attempt to register twice\n");
+ return -EINVAL;
+ }
+
+ rc = cdev_add(&teedev->cdev, teedev->dev.devt, 1);
+ if (rc) {
+ dev_err(&teedev->dev,
+ "unable to cdev_add() %s, major %d, minor %d, err=%d\n",
+ teedev->name, MAJOR(teedev->dev.devt),
+ MINOR(teedev->dev.devt), rc);
+ return rc;
+ }
+
+ rc = device_add(&teedev->dev);
+ if (rc) {
+ dev_err(&teedev->dev,
+ "unable to device_add() %s, major %d, minor %d, err=%d\n",
+ teedev->name, MAJOR(teedev->dev.devt),
+ MINOR(teedev->dev.devt), rc);
+ goto err_device_add;
+ }
+
+ rc = sysfs_create_group(&teedev->dev.kobj, &tee_dev_group);
+ if (rc) {
+ dev_err(&teedev->dev,
+ "failed to create sysfs attributes, err=%d\n", rc);
+ goto err_sysfs_create_group;
+ }
+
+ teedev->flags |= TEE_DEVICE_FLAG_REGISTERED;
+ return 0;
+
+err_sysfs_create_group:
+ device_del(&teedev->dev);
+err_device_add:
+ cdev_del(&teedev->cdev);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tee_device_register);
+
+void tee_device_put(struct tee_device *teedev)
+{
+ mutex_lock(&teedev->mutex);
+ /* Shouldn't put in this state */
+ if (!WARN_ON(!teedev->desc)) {
+ teedev->num_users--;
+ if (!teedev->num_users) {
+ teedev->desc = NULL;
+ complete(&teedev->c_no_users);
+ }
+ }
+ mutex_unlock(&teedev->mutex);
+}
+
+bool tee_device_get(struct tee_device *teedev)
+{
+ mutex_lock(&teedev->mutex);
+ if (!teedev->desc) {
+ mutex_unlock(&teedev->mutex);
+ return false;
+ }
+ teedev->num_users++;
+ mutex_unlock(&teedev->mutex);
+ return true;
+}
+
+/**
+ * tee_device_unregister() - Removes a TEE device
+ * @teedev: Device to unregister
+ *
+ * This function should be called to remove the @teedev even if
+ * tee_device_register() hasn't been called yet. Does nothing if
+ * @teedev is NULL.
+ */
+void tee_device_unregister(struct tee_device *teedev)
+{
+ if (!teedev)
+ return;
+
+ if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) {
+ sysfs_remove_group(&teedev->dev.kobj, &tee_dev_group);
+ cdev_del(&teedev->cdev);
+ device_del(&teedev->dev);
+ }
+
+ tee_device_put(teedev);
+ wait_for_completion(&teedev->c_no_users);
+
+ /*
+ * No need to take a mutex any longer now since teedev->desc was
+ * set to NULL before teedev->c_no_users was completed.
+ */
+
+ teedev->pool = NULL;
+
+ put_device(&teedev->dev);
+}
+EXPORT_SYMBOL_GPL(tee_device_unregister);
+
+/**
+ * tee_get_drvdata() - Return driver_data pointer
+ * @teedev: Device containing the driver_data pointer
+ * @returns the driver_data pointer supplied to tee_register().
+ */
+void *tee_get_drvdata(struct tee_device *teedev)
+{
+ return dev_get_drvdata(&teedev->dev);
+}
+EXPORT_SYMBOL_GPL(tee_get_drvdata);
+
+struct match_dev_data {
+ struct tee_ioctl_version_data *vers;
+ const void *data;
+ int (*match)(struct tee_ioctl_version_data *, const void *);
+};
+
+static int match_dev(struct device *dev, const void *data)
+{
+ const struct match_dev_data *match_data = data;
+ struct tee_device *teedev = container_of(dev, struct tee_device, dev);
+
+ teedev->desc->ops->get_version(teedev, match_data->vers);
+ return match_data->match(match_data->vers, match_data->data);
+}
+
+struct tee_context *
+tee_client_open_context(struct tee_context *start,
+ int (*match)(struct tee_ioctl_version_data *,
+ const void *),
+ const void *data, struct tee_ioctl_version_data *vers)
+{
+ struct device *dev = NULL;
+ struct device *put_dev = NULL;
+ struct tee_context *ctx = NULL;
+ struct tee_ioctl_version_data v;
+ struct match_dev_data match_data = { vers ? vers : &v, data, match };
+
+ if (start)
+ dev = &start->teedev->dev;
+
+ do {
+ dev = class_find_device(tee_class, dev, &match_data, match_dev);
+ if (!dev) {
+ ctx = ERR_PTR(-ENOENT);
+ break;
+ }
+
+ put_device(put_dev);
+ put_dev = dev;
+
+ ctx = teedev_open(container_of(dev, struct tee_device, dev));
+ } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM);
+
+ put_device(put_dev);
+ return ctx;
+}
+EXPORT_SYMBOL_GPL(tee_client_open_context);
+
+void tee_client_close_context(struct tee_context *ctx)
+{
+ teedev_close_context(ctx);
+}
+EXPORT_SYMBOL_GPL(tee_client_close_context);
+
+void tee_client_get_version(struct tee_context *ctx,
+ struct tee_ioctl_version_data *vers)
+{
+ ctx->teedev->desc->ops->get_version(ctx->teedev, vers);
+}
+EXPORT_SYMBOL_GPL(tee_client_get_version);
+
+int tee_client_open_session(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param)
+{
+ if (!ctx->teedev->desc->ops->open_session)
+ return -EINVAL;
+ return ctx->teedev->desc->ops->open_session(ctx, arg, param);
+}
+EXPORT_SYMBOL_GPL(tee_client_open_session);
+
+int tee_client_close_session(struct tee_context *ctx, u32 session)
+{
+ if (!ctx->teedev->desc->ops->close_session)
+ return -EINVAL;
+ return ctx->teedev->desc->ops->close_session(ctx, session);
+}
+EXPORT_SYMBOL_GPL(tee_client_close_session);
+
+int tee_client_invoke_func(struct tee_context *ctx,
+ struct tee_ioctl_invoke_arg *arg,
+ struct tee_param *param)
+{
+ if (!ctx->teedev->desc->ops->invoke_func)
+ return -EINVAL;
+ return ctx->teedev->desc->ops->invoke_func(ctx, arg, param);
+}
+EXPORT_SYMBOL_GPL(tee_client_invoke_func);
+
+static int __init tee_init(void)
+{
+ int rc;
+
+ tee_class = class_create(THIS_MODULE, "tee");
+ if (IS_ERR(tee_class)) {
+ pr_err("couldn't create class\n");
+ return PTR_ERR(tee_class);
+ }
+
+ rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee");
+ if (rc) {
+ pr_err("failed to allocate char dev region\n");
+ class_destroy(tee_class);
+ tee_class = NULL;
+ }
+
+ pr_info("succeeded\n");
+
+ return rc;
+}
+
+static void __exit tee_exit(void)
+{
+ class_destroy(tee_class);
+ tee_class = NULL;
+ unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
+}
+
+subsys_initcall(tee_init);
+module_exit(tee_exit);
+
+MODULE_AUTHOR("Linaro");
+MODULE_DESCRIPTION("TEE Driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tee/tee_core_kern_api.h b/drivers/tee/tee_core_kern_api.h
new file mode 100644
index 00000000..b2718410
--- /dev/null
+++ b/drivers/tee/tee_core_kern_api.h
@@ -0,0 +1,405 @@
+/**
+ * Copyright (c) 2015-2019 Shanghai Fullhan Microelectronics Co., Ltd.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2019-03-22 wangyl first version
+ *
+ */
+
+#ifndef __TEE_CORE_KERN_API_H__
+#define __TEE_CORE_KERN_API_H__
+
+
+static int tee_ioctl_version_kern(struct tee_context *ctx,
+ struct tee_ioctl_version_data *uvers)
+{
+ struct tee_ioctl_version_data vers;
+
+ ctx->teedev->desc->ops->get_version(ctx->teedev, &vers);
+
+ if (ctx->teedev->desc->flags & TEE_DESC_PRIVILEGED)
+ vers.gen_caps |= TEE_GEN_CAP_PRIVILEGED;
+
+ memcpy(uvers, &vers, sizeof(vers));
+
+ return 0;
+}
+
+
+static int tee_ioctl_shm_alloc_kern(struct tee_context *ctx,
+ struct tee_ioctl_shm_alloc_data *udata)
+{
+ struct tee_ioctl_shm_alloc_data data;
+ struct tee_shm *shm;
+
+ memcpy(&data, udata, sizeof(data));
+
+ /* Currently no input flags are supported */
+ if (data.flags)
+ return -EINVAL;
+
+ shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ data.id = shm->id;
+ data.flags = shm->flags;
+ data.size = shm->size;
+
+ memcpy(udata, &data, sizeof(data));
+
+ return (int)shm->kaddr;
+}
+
+static int
+tee_ioctl_shm_register_kern(struct tee_context *ctx,
+ struct tee_ioctl_shm_register_data *udata)
+{
+ long ret;
+ struct tee_ioctl_shm_register_data data;
+ struct tee_shm *shm;
+
+ memcpy(&data, udata, sizeof(data));
+
+ /* Currently no input flags are supported */
+ if (data.flags)
+ return -EINVAL;
+
+ shm = tee_shm_register(ctx, data.addr, data.length,
+ TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ data.id = shm->id;
+ data.flags = shm->flags;
+ data.length = shm->size;
+
+ memcpy(udata, &data, sizeof(data));
+
+ ret = tee_shm_get_fd(shm);
+ /*
+ * When user space closes the file descriptor the shared memory
+ * should be freed or if tee_shm_get_fd() failed then it will
+ * be freed immediately.
+ */
+ tee_shm_put(shm);
+ return ret;
+}
+
+static int tee_ioctl_shm_register_fd_kern(struct tee_context *ctx,
+ struct tee_ioctl_shm_register_fd_data *udata)
+{
+ struct tee_ioctl_shm_register_fd_data data;
+ struct tee_shm *shm;
+ long ret;
+
+ memcpy(&data, udata, sizeof(data));
+
+ /* Currently no input flags are supported */
+ if (data.flags)
+ return -EINVAL;
+
+ shm = tee_shm_register_fd(ctx, data.fd);
+ if (IS_ERR_OR_NULL(shm))
+ return -EINVAL;
+
+ data.id = shm->id;
+ data.flags = shm->flags;
+ data.size = shm->size;
+
+ memcpy(udata, &data, sizeof(data));
+
+ ret = tee_shm_get_fd(shm);
+
+ /*
+ * When user space closes the file descriptor the shared memory
+ * should be freed or if tee_shm_get_fd() failed then it will
+ * be freed immediately.
+ */
+ tee_shm_put(shm);
+ return ret;
+}
+
+static int params_from_user_kern(struct tee_context *ctx, struct tee_param *params,
+ size_t num_params,
+ struct tee_ioctl_param __user *uparams)
+{
+ size_t n;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_shm *shm;
+ struct tee_ioctl_param ip;
+
+ memcpy(&ip, uparams + n, sizeof(ip));
+
+ /* All unused attribute bits has to be zero */
+ if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_MASK)
+ return -EINVAL;
+
+ params[n].attr = ip.attr;
+ switch (ip.attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ params[n].u.value.a = ip.a;
+ params[n].u.value.b = ip.b;
+ params[n].u.value.c = ip.c;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ /*
+ * If we fail to get a pointer to a shared memory
+ * object (and increase the ref count) from an
+ * identifier we return an error. All pointers that
+ * has been added in params have an increased ref
+ * count. It's the callers responibility to do
+ * tee_shm_put() on all resolved pointers.
+ */
+ shm = tee_shm_get_from_id(ctx, ip.c);
+ if (IS_ERR(shm))
+ return PTR_ERR(shm);
+
+ /*
+ * Ensure offset + size does not overflow offset
+ * and does not overflow the size of the referred
+ * shared memory object.
+ */
+ if ((ip.a + ip.b) < ip.a ||
+ (ip.a + ip.b) > shm->size) {
+ tee_shm_put(shm);
+ tee_shm_free(shm);
+ return -EINVAL;
+ }
+
+ params[n].u.memref.shm_offs = ip.a;
+ params[n].u.memref.size = ip.b;
+ params[n].u.memref.shm = shm;
+ break;
+ default:
+ /* Unknown attribute */
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int params_to_user_kern(struct tee_ioctl_param __user *uparams,
+ size_t num_params, struct tee_param *params)
+{
+ size_t n;
+
+ for (n = 0; n < num_params; n++) {
+ struct tee_ioctl_param __user *up = uparams + n;
+ struct tee_param *p = params + n;
+
+ switch (p->attr) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+ up->a = p->u.value.a;
+ up->b = p->u.value.b;
+ up->c = p->u.value.c;
+ break;
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ up->b = (u64)p->u.memref.size;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+static int tee_ioctl_open_session_kern(struct tee_context *ctx,
+ struct tee_ioctl_buf_data *ubuf)
+{
+ int rc;
+ size_t n;
+ struct tee_ioctl_buf_data buf;
+ struct tee_ioctl_open_session_arg __user *uarg;
+ struct tee_ioctl_open_session_arg arg;
+ struct tee_ioctl_param __user *uparams = NULL;
+ struct tee_param *params = NULL;
+ bool have_session = false;
+
+ if (!ctx->teedev->desc->ops->open_session)
+ return -EINVAL;
+
+ memcpy(&buf, ubuf, sizeof(buf));
+
+ if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+ buf.buf_len < sizeof(struct tee_ioctl_open_session_arg))
+ return -EINVAL;
+
+ uarg = u64_to_user_ptr(buf.buf_ptr);
+ memcpy(&arg, uarg, sizeof(arg));
+
+ if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
+ return -EINVAL;
+
+ if (arg.num_params) {
+ params = kcalloc(arg.num_params, sizeof(struct tee_param),
+ GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ uparams = uarg->params;
+ rc = params_from_user_kern(ctx, params, arg.num_params, uparams);
+ if (rc)
+ goto out;
+ }
+
+ rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params);
+ if (rc)
+ goto out;
+ have_session = true;
+
+ uarg->session = arg.session;
+ uarg->ret = arg.ret;
+ uarg->ret_origin = arg.ret_origin;
+
+ rc = params_to_user_kern(uparams, arg.num_params, params);
+out:
+ /*
+ * If we've succeeded to open the session but failed to communicate
+ * it back to user space, close the session again to avoid leakage.
+ */
+ if (rc && have_session && ctx->teedev->desc->ops->close_session)
+ ctx->teedev->desc->ops->close_session(ctx, arg.session);
+
+ if (params) {
+ /* Decrease ref count for all valid shared memory pointers */
+ for (n = 0; n < arg.num_params; n++)
+ if (tee_param_is_memref(params + n) &&
+ params[n].u.memref.shm) {
+ tee_shm_put(params[n].u.memref.shm);
+ tee_shm_free(params[n].u.memref.shm);
+ }
+ kfree(params);
+ }
+
+ return rc;
+}
+
+static int tee_ioctl_invoke_kern(struct tee_context *ctx,
+ struct tee_ioctl_buf_data *ubuf)
+{
+ int rc;
+ size_t n;
+ struct tee_ioctl_buf_data buf;
+ struct tee_ioctl_invoke_arg __user *uarg;
+ struct tee_ioctl_invoke_arg arg;
+ struct tee_ioctl_param __user *uparams = NULL;
+ struct tee_param *params = NULL;
+
+ if (!ctx->teedev->desc->ops->invoke_func)
+ return -EINVAL;
+
+ memcpy(&buf, ubuf, sizeof(buf));
+
+ if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+ buf.buf_len < sizeof(struct tee_ioctl_invoke_arg))
+ return -EINVAL;
+
+ uarg = u64_to_user_ptr(buf.buf_ptr);
+ memcpy(&arg, uarg, sizeof(arg));
+
+ if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
+ return -EINVAL;
+
+ if (arg.num_params) {
+ params = kcalloc(arg.num_params, sizeof(struct tee_param),
+ GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ uparams = uarg->params;
+ rc = params_from_user_kern(ctx, params, arg.num_params, uparams);
+ if (rc)
+ goto out;
+ }
+
+ rc = ctx->teedev->desc->ops->invoke_func(ctx, &arg, params);
+ if (rc)
+ goto out;
+
+ uarg->ret = arg.ret;
+ uarg->ret_origin = arg.ret_origin;
+
+ rc = params_to_user_kern(uparams, arg.num_params, params);
+out:
+ if (params) {
+ /* Decrease ref count for all valid shared memory pointers */
+ for (n = 0; n < arg.num_params; n++)
+ if (tee_param_is_memref(params + n) &&
+ params[n].u.memref.shm) {
+ tee_shm_put(params[n].u.memref.shm);
+ tee_shm_free(params[n].u.memref.shm);
+ }
+ kfree(params);
+ }
+ return rc;
+}
+
+static int tee_ioctl_cancel_kern(struct tee_context *ctx,
+ struct tee_ioctl_cancel_arg *uarg)
+{
+ struct tee_ioctl_cancel_arg arg;
+
+ if (!ctx->teedev->desc->ops->cancel_req)
+ return -EINVAL;
+
+ memcpy(&arg, uarg, sizeof(arg));
+
+ return ctx->teedev->desc->ops->cancel_req(ctx, arg.cancel_id,
+ arg.session);
+}
+
+static int
+tee_ioctl_close_session_kern(struct tee_context *ctx,
+ struct tee_ioctl_close_session_arg *uarg)
+{
+ struct tee_ioctl_close_session_arg arg;
+
+ if (!ctx->teedev->desc->ops->close_session)
+ return -EINVAL;
+
+ memcpy(&arg, uarg, sizeof(arg));
+
+ return ctx->teedev->desc->ops->close_session(ctx, arg.session);
+}
+
+long tee_ioctl_kern(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct tee_context *ctx = filp->private_data;
+ void __user *uarg = (void __user *)arg;
+
+ pr_debug("%x\n", cmd);
+ switch (cmd) {
+ case TEE_IOC_VERSION:
+ return tee_ioctl_version_kern(ctx, uarg);
+ case TEE_IOC_SHM_ALLOC:
+ return tee_ioctl_shm_alloc_kern(ctx, uarg);
+ case TEE_IOC_SHM_REGISTER:
+ return tee_ioctl_shm_register_kern(ctx, uarg);
+ case TEE_IOC_SHM_REGISTER_FD:
+ return tee_ioctl_shm_register_fd_kern(ctx, uarg);
+ case TEE_IOC_OPEN_SESSION:
+ return tee_ioctl_open_session_kern(ctx, uarg);
+ case TEE_IOC_INVOKE:
+ return tee_ioctl_invoke_kern(ctx, uarg);
+ case TEE_IOC_CANCEL:
+ return tee_ioctl_cancel_kern(ctx, uarg);
+ case TEE_IOC_CLOSE_SESSION:
+ return tee_ioctl_close_session_kern(ctx, uarg);
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL_GPL(tee_ioctl_kern);
+
+#endif
diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
new file mode 100644
index 00000000..85d99d62
--- /dev/null
+++ b/drivers/tee/tee_private.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef TEE_PRIVATE_H
+#define TEE_PRIVATE_H
+
+#include <linux/cdev.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+/**
+ * struct tee_shm_pool - shared memory pool
+ * @private_mgr: pool manager for shared memory only between kernel
+ * and secure world
+ * @dma_buf_mgr: pool manager for shared memory exported to user space
+ */
+struct tee_shm_pool {
+ struct tee_shm_pool_mgr *private_mgr;
+ struct tee_shm_pool_mgr *dma_buf_mgr;
+};
+
+#define TEE_DEVICE_FLAG_REGISTERED 0x1
+#define TEE_MAX_DEV_NAME_LEN 32
+
+/**
+ * struct tee_device - TEE Device representation
+ * @name: name of device
+ * @desc: description of device
+ * @id: unique id of device
+ * @flags: represented by TEE_DEVICE_FLAG_REGISTERED above
+ * @dev: embedded basic device structure
+ * @cdev: embedded cdev
+ * @num_users: number of active users of this device
+ * @c_no_user: completion used when unregistering the device
+ * @mutex: mutex protecting @num_users and @idr
+ * @idr: register of shared memory object allocated on this device
+ * @pool: shared memory pool
+ */
+struct tee_device {
+ char name[TEE_MAX_DEV_NAME_LEN];
+ const struct tee_desc *desc;
+ int id;
+ unsigned int flags;
+
+ struct device dev;
+ struct cdev cdev;
+
+ size_t num_users;
+ struct completion c_no_users;
+ struct mutex mutex; /* protects num_users and idr */
+
+ struct idr idr;
+ struct tee_shm_pool *pool;
+};
+
+int tee_shm_init(void);
+
+int tee_shm_get_fd(struct tee_shm *shm);
+
+bool tee_device_get(struct tee_device *teedev);
+void tee_device_put(struct tee_device *teedev);
+
+void teedev_ctx_get(struct tee_context *ctx);
+void teedev_ctx_put(struct tee_context *ctx);
+
+#endif /*TEE_PRIVATE_H*/
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
new file mode 100644
index 00000000..2be75482
--- /dev/null
+++ b/drivers/tee/tee_shm.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/fdtable.h>
+#include <linux/idr.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include "tee_private.h"
+
+/* extra references appended to shm object for registered shared memory */
+struct tee_shm_dmabuf_ref {
+ struct tee_shm shm;
+ struct dma_buf *dmabuf;
+ struct dma_buf_attachment *attach;
+ struct sg_table *sgt;
+};
+
+static void tee_shm_release(struct tee_shm *shm)
+{
+ struct tee_device *teedev = shm->teedev;
+
+ mutex_lock(&teedev->mutex);
+ idr_remove(&teedev->idr, shm->id);
+ if (shm->ctx)
+ list_del(&shm->link);
+ mutex_unlock(&teedev->mutex);
+
+ if (shm->flags & TEE_SHM_EXT_DMA_BUF) {
+ struct tee_shm_dmabuf_ref *ref;
+
+ ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
+ dma_buf_unmap_attachment(ref->attach, ref->sgt,
+ DMA_BIDIRECTIONAL);
+ dma_buf_detach(shm->dmabuf, ref->attach);
+ dma_buf_put(ref->dmabuf);
+ } else if (shm->flags & TEE_SHM_POOL) {
+ struct tee_shm_pool_mgr *poolm;
+
+ if (shm->flags & TEE_SHM_DMA_BUF)
+ poolm = teedev->pool->dma_buf_mgr;
+ else
+ poolm = teedev->pool->private_mgr;
+
+ poolm->ops->free(poolm, shm);
+ } else if (shm->flags & TEE_SHM_REGISTER) {
+ size_t n;
+ int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
+
+ if (rc)
+ dev_err(teedev->dev.parent,
+ "unregister shm %p failed: %d", shm, rc);
+
+ for (n = 0; n < shm->num_pages; n++)
+ put_page(shm->pages[n]);
+
+ kfree(shm->pages);
+ }
+
+ if (shm->ctx)
+ teedev_ctx_put(shm->ctx);
+
+ kfree(shm);
+ tee_device_put(teedev);
+}
+
+static struct sg_table *tee_shm_op_map_dma_buf(struct dma_buf_attachment
+ *attach, enum dma_data_direction dir)
+{
+ return NULL;
+}
+
+static void tee_shm_op_unmap_dma_buf(struct dma_buf_attachment *attach,
+ struct sg_table *table,
+ enum dma_data_direction dir)
+{
+}
+
+static void tee_shm_op_release(struct dma_buf *dmabuf)
+{
+ struct tee_shm *shm = dmabuf->priv;
+
+ tee_shm_release(shm);
+}
+
+static void *tee_shm_op_map_atomic(struct dma_buf *dmabuf, unsigned long pgnum)
+{
+ return NULL;
+}
+
+static void *tee_shm_op_map(struct dma_buf *dmabuf, unsigned long pgnum)
+{
+ return NULL;
+}
+
+static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+ struct tee_shm *shm = dmabuf->priv;
+ size_t size = vma->vm_end - vma->vm_start;
+
+ /* Refuse sharing shared memory provided by application */
+ if (shm->flags & TEE_SHM_REGISTER)
+ return -EINVAL;
+
+ return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT,
+ size, vma->vm_page_prot);
+}
+
+static const struct dma_buf_ops tee_shm_dma_buf_ops = {
+ .map_dma_buf = tee_shm_op_map_dma_buf,
+ .unmap_dma_buf = tee_shm_op_unmap_dma_buf,
+ .release = tee_shm_op_release,
+ .kmap_atomic = tee_shm_op_map_atomic,
+ .kmap = tee_shm_op_map,
+ .mmap = tee_shm_op_mmap,
+};
+
+static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
+ struct tee_device *teedev,
+ size_t size, u32 flags)
+{
+ struct tee_shm_pool_mgr *poolm = NULL;
+ struct tee_shm *shm;
+ void *ret;
+ int rc;
+
+ if (ctx && ctx->teedev != teedev) {
+ dev_err(teedev->dev.parent, "ctx and teedev mismatch\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!(flags & TEE_SHM_MAPPED)) {
+ dev_err(teedev->dev.parent,
+ "only mapped allocations supported\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) {
+ dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!tee_device_get(teedev))
+ return ERR_PTR(-EINVAL);
+
+ if (!teedev->pool) {
+ /* teedev has been detached from driver */
+ ret = ERR_PTR(-EINVAL);
+ goto err_dev_put;
+ }
+
+ shm = kzalloc(sizeof(*shm), GFP_KERNEL);
+ if (!shm) {
+ ret = ERR_PTR(-ENOMEM);
+ goto err_dev_put;
+ }
+
+ shm->flags = flags | TEE_SHM_POOL;
+ shm->teedev = teedev;
+ shm->ctx = ctx;
+ if (flags & TEE_SHM_DMA_BUF)
+ poolm = teedev->pool->dma_buf_mgr;
+ else
+ poolm = teedev->pool->private_mgr;
+
+ rc = poolm->ops->alloc(poolm, shm, size);
+ if (rc) {
+ ret = ERR_PTR(rc);
+ goto err_kfree;
+ }
+
+ mutex_lock(&teedev->mutex);
+ shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
+ mutex_unlock(&teedev->mutex);
+ if (shm->id < 0) {
+ ret = ERR_PTR(shm->id);
+ goto err_pool_free;
+ }
+
+ if (flags & TEE_SHM_DMA_BUF) {
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+ exp_info.ops = &tee_shm_dma_buf_ops;
+ exp_info.size = shm->size;
+ exp_info.flags = O_RDWR;
+ exp_info.priv = shm;
+
+ shm->dmabuf = dma_buf_export(&exp_info);
+ if (IS_ERR(shm->dmabuf)) {
+ ret = ERR_CAST(shm->dmabuf);
+ goto err_rem;
+ }
+ }
+
+ if (ctx) {
+ teedev_ctx_get(ctx);
+ mutex_lock(&teedev->mutex);
+ list_add_tail(&shm->link, &ctx->list_shm);
+ mutex_unlock(&teedev->mutex);
+ }
+
+ return shm;
+err_rem:
+ mutex_lock(&teedev->mutex);
+ idr_remove(&teedev->idr, shm->id);
+ mutex_unlock(&teedev->mutex);
+err_pool_free:
+ poolm->ops->free(poolm, shm);
+err_kfree:
+ kfree(shm);
+err_dev_put:
+ tee_device_put(teedev);
+ return ret;
+}
+
+/**
+ * tee_shm_alloc() - Allocate shared memory
+ * @ctx: Context that allocates the shared memory
+ * @size: Requested size of shared memory
+ * @flags: Flags setting properties for the requested shared memory.
+ *
+ * Memory allocated as global shared memory is automatically freed when the
+ * TEE file pointer is closed. The @flags field uses the bits defined by
+ * TEE_SHM_* in <linux/tee_drv.h>. TEE_SHM_MAPPED must currently always be
+ * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and
+ * associated with a dma-buf handle, else driver private memory.
+ */
+struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
+{
+ return __tee_shm_alloc(ctx, ctx->teedev, size, flags);
+}
+EXPORT_SYMBOL_GPL(tee_shm_alloc);
+
+struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size)
+{
+ return __tee_shm_alloc(NULL, teedev, size, TEE_SHM_MAPPED);
+}
+EXPORT_SYMBOL_GPL(tee_shm_priv_alloc);
+
+struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
+ size_t length, u32 flags)
+{
+ struct tee_device *teedev = ctx->teedev;
+ const u32 req_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED;
+ struct tee_shm *shm;
+ void *ret;
+ int rc;
+ int num_pages;
+ unsigned long start;
+
+ if (flags != req_flags)
+ return ERR_PTR(-ENOTSUPP);
+
+ if (!tee_device_get(teedev))
+ return ERR_PTR(-EINVAL);
+
+ if (!teedev->desc->ops->shm_register ||
+ !teedev->desc->ops->shm_unregister) {
+ tee_device_put(teedev);
+ return ERR_PTR(-ENOTSUPP);
+ }
+
+ teedev_ctx_get(ctx);
+
+ shm = kzalloc(sizeof(*shm), GFP_KERNEL);
+ if (!shm) {
+ ret = ERR_PTR(-ENOMEM);
+ goto err;
+ }
+
+ shm->flags = flags | TEE_SHM_REGISTER;
+ shm->teedev = teedev;
+ shm->ctx = ctx;
+ shm->id = -1;
+ start = rounddown(addr, PAGE_SIZE);
+ shm->offset = addr - start;
+ shm->size = length;
+ num_pages = (roundup(addr + length, PAGE_SIZE) - start) / PAGE_SIZE;
+ shm->pages = kcalloc(num_pages, sizeof(*shm->pages), GFP_KERNEL);
+ if (!shm->pages) {
+ ret = ERR_PTR(-ENOMEM);
+ goto err;
+ }
+
+ rc = get_user_pages_fast(start, num_pages, 1, shm->pages);
+ if (rc > 0)
+ shm->num_pages = rc;
+ if (rc != num_pages) {
+ if (rc >= 0)
+ rc = -ENOMEM;
+ ret = ERR_PTR(rc);
+ goto err;
+ }
+
+ mutex_lock(&teedev->mutex);
+ shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
+ mutex_unlock(&teedev->mutex);
+
+ if (shm->id < 0) {
+ ret = ERR_PTR(shm->id);
+ goto err;
+ }
+
+ rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
+ shm->num_pages, start);
+ if (rc) {
+ ret = ERR_PTR(rc);
+ goto err;
+ }
+
+ if (flags & TEE_SHM_DMA_BUF) {
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+ exp_info.ops = &tee_shm_dma_buf_ops;
+ exp_info.size = shm->size;
+ exp_info.flags = O_RDWR;
+ exp_info.priv = shm;
+
+ shm->dmabuf = dma_buf_export(&exp_info);
+ if (IS_ERR(shm->dmabuf)) {
+ ret = ERR_CAST(shm->dmabuf);
+ teedev->desc->ops->shm_unregister(ctx, shm);
+ goto err;
+ }
+ }
+
+ mutex_lock(&teedev->mutex);
+ list_add_tail(&shm->link, &ctx->list_shm);
+ mutex_unlock(&teedev->mutex);
+
+ return shm;
+err:
+ if (shm) {
+ size_t n;
+
+ if (shm->id >= 0) {
+ mutex_lock(&teedev->mutex);
+ idr_remove(&teedev->idr, shm->id);
+ mutex_unlock(&teedev->mutex);
+ }
+ if (shm->pages) {
+ for (n = 0; n < shm->num_pages; n++)
+ put_page(shm->pages[n]);
+ kfree(shm->pages);
+ }
+ }
+ kfree(shm);
+ teedev_ctx_put(ctx);
+ tee_device_put(teedev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tee_shm_register);
+
+struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd)
+{
+ struct tee_shm_dmabuf_ref *ref;
+ void *rc;
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+ if (!tee_device_get(ctx->teedev))
+ return ERR_PTR(-EINVAL);
+
+ teedev_ctx_get(ctx);
+
+ ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ if (!ref) {
+ rc = ERR_PTR(-ENOMEM);
+ goto err;
+ }
+
+ ref->shm.ctx = ctx;
+ ref->shm.teedev = ctx->teedev;
+ ref->shm.id = -1;
+
+ ref->dmabuf = dma_buf_get(fd);
+ if (!ref->dmabuf) {
+ rc = ERR_PTR(-EINVAL);
+ goto err;
+ }
+
+ ref->attach = dma_buf_attach(ref->dmabuf, &ref->shm.teedev->dev);
+ if (IS_ERR_OR_NULL(ref->attach)) {
+ rc = ERR_PTR(-EINVAL);
+ goto err;
+ }
+
+ ref->sgt = dma_buf_map_attachment(ref->attach, DMA_BIDIRECTIONAL);
+ if (IS_ERR_OR_NULL(ref->sgt)) {
+ rc = ERR_PTR(-EINVAL);
+ goto err;
+ }
+
+ if (sg_nents(ref->sgt->sgl) != 1) {
+ rc = ERR_PTR(-EINVAL);
+ goto err;
+ }
+
+ ref->shm.paddr = sg_dma_address(ref->sgt->sgl);
+ ref->shm.size = sg_dma_len(ref->sgt->sgl);
+ ref->shm.flags = TEE_SHM_DMA_BUF | TEE_SHM_EXT_DMA_BUF;
+
+ mutex_lock(&ref->shm.teedev->mutex);
+ ref->shm.id = idr_alloc(&ref->shm.teedev->idr, &ref->shm,
+ 1, 0, GFP_KERNEL);
+ mutex_unlock(&ref->shm.teedev->mutex);
+ if (ref->shm.id < 0) {
+ rc = ERR_PTR(ref->shm.id);
+ goto err;
+ }
+
+ /* export a dmabuf to later get a userland ref */
+ exp_info.ops = &tee_shm_dma_buf_ops;
+ exp_info.size = ref->shm.size;
+ exp_info.flags = O_RDWR;
+ exp_info.priv = &ref->shm;
+
+ ref->shm.dmabuf = dma_buf_export(&exp_info);
+ if (IS_ERR(ref->shm.dmabuf)) {
+ rc = ERR_PTR(-EINVAL);
+ goto err;
+ }
+
+ mutex_lock(&ref->shm.teedev->mutex);
+ list_add_tail(&ref->shm.link, &ctx->list_shm);
+ mutex_unlock(&ref->shm.teedev->mutex);
+
+ return &ref->shm;
+
+err:
+ if (ref) {
+ if (ref->shm.id >= 0) {
+ mutex_lock(&ctx->teedev->mutex);
+ idr_remove(&ctx->teedev->idr, ref->shm.id);
+ mutex_unlock(&ctx->teedev->mutex);
+ }
+ if (ref->sgt)
+ dma_buf_unmap_attachment(ref->attach, ref->sgt,
+ DMA_BIDIRECTIONAL);
+ if (ref->attach)
+ dma_buf_detach(ref->dmabuf, ref->attach);
+ if (ref->dmabuf)
+ dma_buf_put(ref->dmabuf);
+ }
+ kfree(ref);
+ teedev_ctx_put(ctx);
+ tee_device_put(ctx->teedev);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tee_shm_register_fd);
+
+/**
+ * tee_shm_get_fd() - Increase reference count and return file descriptor
+ * @shm: Shared memory handle
+ * @returns user space file descriptor to shared memory
+ */
+int tee_shm_get_fd(struct tee_shm *shm)
+{
+ int fd;
+
+ if (!(shm->flags & TEE_SHM_DMA_BUF))
+ return -EINVAL;
+
+ get_dma_buf(shm->dmabuf);
+ fd = dma_buf_fd(shm->dmabuf, O_CLOEXEC);
+ if (fd < 0)
+ dma_buf_put(shm->dmabuf);
+ return fd;
+}
+
+/**
+ * tee_shm_free() - Free shared memory
+ * @shm: Handle to shared memory to free
+ */
+void tee_shm_free(struct tee_shm *shm)
+{
+ /*
+ * dma_buf_put() decreases the dmabuf reference counter and will
+ * call tee_shm_release() when the last reference is gone.
+ *
+ * In the case of driver private memory we call tee_shm_release
+ * directly instead as it doesn't have a reference counter.
+ */
+ if (shm->flags & TEE_SHM_DMA_BUF)
+ dma_buf_put(shm->dmabuf);
+ else
+ tee_shm_release(shm);
+}
+EXPORT_SYMBOL_GPL(tee_shm_free);
+
+/**
+ * tee_shm_va2pa() - Get physical address of a virtual address
+ * @shm: Shared memory handle
+ * @va: Virtual address to tranlsate
+ * @pa: Returned physical address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa)
+{
+ if (!(shm->flags & TEE_SHM_MAPPED))
+ return -EINVAL;
+ /* Check that we're in the range of the shm */
+ if ((char *)va < (char *)shm->kaddr)
+ return -EINVAL;
+ if ((char *)va >= ((char *)shm->kaddr + shm->size))
+ return -EINVAL;
+
+ return tee_shm_get_pa(
+ shm, (unsigned long)va - (unsigned long)shm->kaddr, pa);
+}
+EXPORT_SYMBOL_GPL(tee_shm_va2pa);
+
+/**
+ * tee_shm_pa2va() - Get virtual address of a physical address
+ * @shm: Shared memory handle
+ * @pa: Physical address to tranlsate
+ * @va: Returned virtual address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va)
+{
+ if (!(shm->flags & TEE_SHM_MAPPED))
+ return -EINVAL;
+ /* Check that we're in the range of the shm */
+ if (pa < shm->paddr)
+ return -EINVAL;
+ if (pa >= (shm->paddr + shm->size))
+ return -EINVAL;
+
+ if (va) {
+ void *v = tee_shm_get_va(shm, pa - shm->paddr);
+
+ if (IS_ERR(v))
+ return PTR_ERR(v);
+ *va = v;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tee_shm_pa2va);
+
+/**
+ * tee_shm_get_va() - Get virtual address of a shared memory plus an offset
+ * @shm: Shared memory handle
+ * @offs: Offset from start of this shared memory
+ * @returns virtual address of the shared memory + offs if offs is within
+ * the bounds of this shared memory, else an ERR_PTR
+ */
+void *tee_shm_get_va(struct tee_shm *shm, size_t offs)
+{
+ if (!(shm->flags & TEE_SHM_MAPPED))
+ return ERR_PTR(-EINVAL);
+ if (offs >= shm->size)
+ return ERR_PTR(-EINVAL);
+ return (char *)shm->kaddr + offs;
+}
+EXPORT_SYMBOL_GPL(tee_shm_get_va);
+
+/**
+ * tee_shm_get_pa() - Get physical address of a shared memory plus an offset
+ * @shm: Shared memory handle
+ * @offs: Offset from start of this shared memory
+ * @pa: Physical address to return
+ * @returns 0 if offs is within the bounds of this shared memory, else an
+ * error code.
+ */
+int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa)
+{
+ if (offs >= shm->size)
+ return -EINVAL;
+ if (pa)
+ *pa = shm->paddr + offs;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tee_shm_get_pa);
+
+/**
+ * tee_shm_get_from_id() - Find shared memory object and increase reference
+ * count
+ * @ctx: Context owning the shared memory
+ * @id: Id of shared memory object
+ * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure
+ */
+struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id)
+{
+ struct tee_device *teedev;
+ struct tee_shm *shm;
+
+ if (!ctx)
+ return ERR_PTR(-EINVAL);
+
+ teedev = ctx->teedev;
+ mutex_lock(&teedev->mutex);
+ shm = idr_find(&teedev->idr, id);
+ if (!shm || shm->ctx != ctx)
+ shm = ERR_PTR(-EINVAL);
+ else if (shm->flags & TEE_SHM_DMA_BUF)
+ get_dma_buf(shm->dmabuf);
+ mutex_unlock(&teedev->mutex);
+ return shm;
+}
+EXPORT_SYMBOL_GPL(tee_shm_get_from_id);
+
+/**
+ * tee_shm_put() - Decrease reference count on a shared memory handle
+ * @shm: Shared memory handle
+ */
+void tee_shm_put(struct tee_shm *shm)
+{
+ if (shm->flags & TEE_SHM_DMA_BUF)
+ dma_buf_put(shm->dmabuf);
+}
+EXPORT_SYMBOL_GPL(tee_shm_put);
diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
new file mode 100644
index 00000000..e6d4b9e4
--- /dev/null
+++ b/drivers/tee/tee_shm_pool.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/genalloc.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include "tee_private.h"
+
+static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm,
+ struct tee_shm *shm, size_t size)
+{
+ unsigned long va;
+ struct gen_pool *genpool = poolm->private_data;
+ size_t s = roundup(size, 1 << genpool->min_alloc_order);
+
+ va = gen_pool_alloc(genpool, s);
+ if (!va)
+ return -ENOMEM;
+
+ memset((void *)va, 0, s);
+ shm->kaddr = (void *)va;
+ shm->paddr = gen_pool_virt_to_phys(genpool, va);
+ shm->size = s;
+ return 0;
+}
+
+static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm,
+ struct tee_shm *shm)
+{
+ gen_pool_free(poolm->private_data, (unsigned long)shm->kaddr,
+ shm->size);
+ shm->kaddr = NULL;
+}
+
+static void pool_op_gen_destroy_poolmgr(struct tee_shm_pool_mgr *poolm)
+{
+ gen_pool_destroy(poolm->private_data);
+ kfree(poolm);
+}
+
+static const struct tee_shm_pool_mgr_ops pool_ops_generic = {
+ .alloc = pool_op_gen_alloc,
+ .free = pool_op_gen_free,
+ .destroy_poolmgr = pool_op_gen_destroy_poolmgr,
+};
+
+/**
+ * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
+ * memory range
+ * @priv_info: Information for driver private shared memory pool
+ * @dmabuf_info: Information for dma-buf shared memory pool
+ *
+ * Start and end of pools will must be page aligned.
+ *
+ * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
+ * in @dmabuf, others will use the range provided by @priv.
+ *
+ * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
+ */
+struct tee_shm_pool *
+tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
+ struct tee_shm_pool_mem_info *dmabuf_info)
+{
+ struct tee_shm_pool_mgr *priv_mgr;
+ struct tee_shm_pool_mgr *dmabuf_mgr;
+ void *rc;
+
+ /*
+ * Create the pool for driver private shared memory
+ */
+ rc = tee_shm_pool_mgr_alloc_res_mem(priv_info->vaddr, priv_info->paddr,
+ priv_info->size,
+ 3 /* 8 byte aligned */);
+ if (IS_ERR(rc))
+ return rc;
+ priv_mgr = rc;
+
+ /*
+ * Create the pool for dma_buf shared memory
+ */
+ rc = tee_shm_pool_mgr_alloc_res_mem(dmabuf_info->vaddr,
+ dmabuf_info->paddr,
+ dmabuf_info->size, PAGE_SHIFT);
+ if (IS_ERR(rc))
+ goto err_free_priv_mgr;
+ dmabuf_mgr = rc;
+
+ rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
+ if (IS_ERR(rc))
+ goto err_free_dmabuf_mgr;
+
+ return rc;
+
+err_free_dmabuf_mgr:
+ tee_shm_pool_mgr_destroy(dmabuf_mgr);
+err_free_priv_mgr:
+ tee_shm_pool_mgr_destroy(priv_mgr);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);
+
+struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr,
+ phys_addr_t paddr,
+ size_t size,
+ int min_alloc_order)
+{
+ const size_t page_mask = PAGE_SIZE - 1;
+ struct tee_shm_pool_mgr *mgr;
+ int rc;
+
+ /* Start and end must be page aligned */
+ if (vaddr & page_mask || paddr & page_mask || size & page_mask)
+ return ERR_PTR(-EINVAL);
+
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+ if (!mgr)
+ return ERR_PTR(-ENOMEM);
+
+ mgr->private_data = gen_pool_create(min_alloc_order, -1);
+ if (!mgr->private_data) {
+ rc = -ENOMEM;
+ goto err;
+ }
+
+ gen_pool_set_algo(mgr->private_data, gen_pool_best_fit, NULL);
+ rc = gen_pool_add_virt(mgr->private_data, vaddr, paddr, size, -1);
+ if (rc) {
+ gen_pool_destroy(mgr->private_data);
+ goto err;
+ }
+
+ mgr->ops = &pool_ops_generic;
+
+ return mgr;
+err:
+ kfree(mgr);
+
+ return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_GPL(tee_shm_pool_mgr_alloc_res_mem);
+
+static bool check_mgr_ops(struct tee_shm_pool_mgr *mgr)
+{
+ return mgr && mgr->ops && mgr->ops->alloc && mgr->ops->free &&
+ mgr->ops->destroy_poolmgr;
+}
+
+struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
+ struct tee_shm_pool_mgr *dmabuf_mgr)
+{
+ struct tee_shm_pool *pool;
+
+ if (!check_mgr_ops(priv_mgr) || !check_mgr_ops(dmabuf_mgr))
+ return ERR_PTR(-EINVAL);
+
+ pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+ if (!pool)
+ return ERR_PTR(-ENOMEM);
+
+ pool->private_mgr = priv_mgr;
+ pool->dma_buf_mgr = dmabuf_mgr;
+
+ return pool;
+}
+EXPORT_SYMBOL_GPL(tee_shm_pool_alloc);
+
+/**
+ * tee_shm_pool_free() - Free a shared memory pool
+ * @pool: The shared memory pool to free
+ *
+ * There must be no remaining shared memory allocated from this pool when
+ * this function is called.
+ */
+void tee_shm_pool_free(struct tee_shm_pool *pool)
+{
+ if (pool->private_mgr)
+ tee_shm_pool_mgr_destroy(pool->private_mgr);
+ if (pool->dma_buf_mgr)
+ tee_shm_pool_mgr_destroy(pool->dma_buf_mgr);
+ kfree(pool);
+}
+EXPORT_SYMBOL_GPL(tee_shm_pool_free);
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index 95103054..0d594a63 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -49,8 +49,14 @@ config CONSOLE_TRANSLATIONS
This enables support for font mapping and Unicode translation
on virtual consoles.
+config DUMMY_CONSOLE
+ bool
+ depends on VT
+ default y
+
+
config VT_CONSOLE
- bool "Support for console on virtual terminal" if EXPERT
+ bool "Support for console on virtual terminal"
depends on VT
default y
---help---
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 5817e239..45858594 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \
- tty_buffer.o tty_port.o tty_mutex.o tty_ldsem.o
+ tty_buffer.o tty_port.o tty_mutex.o tty_ldsem.o tty_baudrate.o
+obj-$(CONFIG_MINITTY_SERIAL) += tty_baudrate.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-$(CONFIG_AUDIT) += tty_audit.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 25c1d7bc..3246a9b7 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -2,7 +2,17 @@
# Serial device configuration
#
-if TTY
+config MINITTY_SERIAL
+ bool "Enable mini TTY for serial ports"
+ depends on !TTY
+ default y
+ help
+ This enables a much smaller TTY implementation that only supports
+ serial ports in a limited capacity. This is however sufficient for
+ many embedded use cases that use serial ports mainly as a debug
+ console where the saving in kernel code size is welcome.
+
+if TTY || MINITTY_SERIAL
menu "Serial drivers"
depends on HAS_IOMEM
@@ -1311,6 +1321,12 @@ config SERIAL_GRLIB_GAISLER_APBUART
select SERIAL_CORE
---help---
Add support for the GRLIB APBUART serial port.
+config SERIAL_FULLHAN
+ tristate "FULLHAN serial support"
+ select SERIAL_CORE
+ select SERIAL_CORE_CONSOLE
+ ---help---
+ Add support for the FULLHAN serial port.
config SERIAL_GRLIB_GAISLER_APBUART_CONSOLE
bool "Console on GRLIB APBUART serial port"
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 1278d376..4e2c989b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -2,7 +2,9 @@
# Makefile for the kernel serial device drivers.
#
-obj-$(CONFIG_SERIAL_CORE) += serial_core.o
+serial_core-$(CONFIG_TTY) := fulltty_serial.o
+serial_core-$(CONFIG_MINITTY_SERIAL) := minitty_serial.o
+obj-$(CONFIG_SERIAL_CORE) += serial_core.o serial_lib.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
@@ -72,6 +74,7 @@ obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
+obj-$(CONFIG_SERIAL_FULLHAN) += fh_serial.o
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x60.o
diff --git a/drivers/tty/serial/fh_serial.c b/drivers/tty/serial/fh_serial.c
new file mode 100644
index 00000000..662e2ee4
--- /dev/null
+++ b/drivers/tty/serial/fh_serial.c
@@ -0,0 +1,1557 @@
+/*
+ * linux/drivers/tty/serial/fh_of_serial.c
+ *
+ * Copyright (C) 2017 Fullhan Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#if defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/kthread.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <asm/irq.h>
+#include <linux/clk.h>
+#include <mach/pmu.h>
+
+#include <linux/completion.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/fh_dmac.h>
+
+#include <mach/fh_uart_plat.h>
+
+#include "fh_serial.h"
+
+#define REG_UART_RBR (0x0000)
+#define REG_UART_THR (0x0000)
+#define REG_UART_DLL (0x0000)
+#define REG_UART_DLH (0x0004)
+#define REG_UART_IER (0x0004)
+#define REG_UART_IIR (0x0008)
+#define REG_UART_FCR (0x0008)
+#define REG_UART_LCR (0x000c)
+#define REG_UART_MCR (0x0010)
+#define REG_UART_LSR (0x0014)
+#define REG_UART_MSR (0x0018)
+#define REG_UART_SCR (0x001c)
+#define REG_UART_FAR (0x0070)
+#define REG_UART_TFR (0x0074)
+#define REG_UART_RFW (0x0078)
+#define REG_UART_USR (0x007c)
+#define REG_UART_TFL (0x0080)
+#define REG_UART_RFL (0x0084)
+#define REG_UART_SRR (0x0088)
+#define REG_UART_SFE (0x0098)
+#define REG_UART_SRT (0x009c)
+#define REG_UART_STET (0x00a0)
+#define REG_UART_HTX (0x00a4)
+#define REG_UART_DMASA (0x00a8)
+#define REG_UART_DLF (0x00C0)
+#define REG_UART_CPR (0x00f4)
+#define REG_UART_UCV (0x00f8)
+#define REG_UART_CTR (0x00fc)
+
+#define FH_SERIAL_NAME "fh-serial"
+#define FH_DRIVE_NAME "ttyS" /* for tty */
+#define FH_DEV_NAME "ttyS" /*for earlyprintk*/
+
+#define UART_READ_RX_DW_FIFO_OK 0
+#define UART_READ_RX_DW_FIFO_TIME_OUT 0xcc
+#define MAP_SIZE 0x100
+
+static struct console fh_serial_console;
+#define FH_SERIAL_CONSOLE (&fh_serial_console)
+
+#define tx_enabled(port) ((port)->unused[0])
+#define rx_enabled(port) ((port)->unused[1])
+
+#define UART_FIFO_BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+#define UART_BAUD BAUDRATE_115200
+#define UART_FIFO UART_INT_RXFIFO_DEPTH_QUARTER
+#define UART_LINE Uart_line_8n2
+#define UART_DEFAULT_BAUD 115200
+/* denominator = (2 ^ DLF_SIZE) when FRACTIONAL_BAUD_DIVISOR Enabled */
+#define DLF_SIZE 4
+
+#define FH_UART_NUMBER 3
+
+#define fh_uart_readl(port, offset) \
+ readl(port->membase + offset)
+#define fh_uart_writel(port, offset, val) \
+ writel((val), port->membase + offset)
+
+static void fh_serial_stop_tx(struct uart_port *port);
+static void fh_serial_start_tx(struct uart_port *port);
+static void fh_serial_stop_rx(struct uart_port *port);
+static void fh_serial_start_rx(struct uart_port *port);
+static unsigned int fh_serial_tx_empty(struct uart_port *port);
+static unsigned int fh_serial_get_mctrl(struct uart_port *port);
+static void fh_serial_set_mctrl(struct uart_port *port, unsigned int mctrl);
+static void fh_serial_break_ctl(struct uart_port *port, int break_state);
+static irqreturn_t fh_uart_rx_chars(int irq, void *dev_id);
+static irqreturn_t fh_uart_tx_chars(int irq, void *dev_id);
+static irqreturn_t fh_uart_isr(int irq, void *dev_id);
+static void fh_serial_shutdown(struct uart_port *port);
+static int fh_serial_startup(struct uart_port *port);
+static void fh_serial_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old);
+static const char *fh_serial_type(struct uart_port *port);
+static void fh_serial_release_port(struct uart_port *port);
+static int fh_serial_request_port(struct uart_port *port);
+static void fh_serial_config_port(struct uart_port *port, int flags);
+static int fh_serial_verify_port(struct uart_port *port,
+ struct serial_struct *ser);
+#ifdef CONFIG_USE_OF
+static int fh_serial_of_configure(void);
+#endif
+static int fh_serial_configure(struct uart_port *port, struct platform_device *op);
+
+static bool fh_uart_dma_chan_filter(struct dma_chan *chan, void *param);
+static void fh_serial_dma_rx_callback(void *arg);
+static void fh_serial_dma_rx_char(void *arg);
+static int uart_dma_set_rx_para(struct uart_port *port, int xfer_len,
+ void (*call_back)(void *arg));
+#ifdef CONFIG_UART_TX_DMA
+static void fh_serial_dma_tx_char_done(void *arg);
+static int uart_dma_set_tx_para(struct uart_port *port, int xfer_len,
+ void (*call_back)(void *arg));
+static void fh_serial_dma_tx_char(struct uart_port *port);
+#endif
+
+static struct uart_ops fh_serial_ops = {
+ .tx_empty = fh_serial_tx_empty,
+ .get_mctrl = fh_serial_get_mctrl,
+ .set_mctrl = fh_serial_set_mctrl,
+ .stop_tx = fh_serial_stop_tx,
+ .start_tx = fh_serial_start_tx,
+ .stop_rx = fh_serial_stop_rx,
+ .break_ctl = fh_serial_break_ctl,
+ .startup = fh_serial_startup,
+ .shutdown = fh_serial_shutdown,
+ .set_termios = fh_serial_set_termios,
+ .type = fh_serial_type,
+ .release_port = fh_serial_release_port,
+ .request_port = fh_serial_request_port,
+ .config_port = fh_serial_config_port,
+ .verify_port = fh_serial_verify_port,
+};
+
+static struct uart_driver fh_serial_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = FH_DRIVE_NAME,
+ .nr = FH_UART_NUMBER,
+ .cons = FH_SERIAL_CONSOLE,
+ .dev_name = FH_DEV_NAME,
+ .major = TTY_MAJOR,
+ .minor = 64,
+};
+
+#ifdef CONFIG_USE_OF
+struct uart_port fh_serial_ports[FH_UART_NUMBER];
+#else
+extern struct uart_port fh_serial_ports[FH_UART_NUMBER];
+#endif
+
+static struct fh_uart_dma *uart_dma[FH_UART_NUMBER];
+
+static inline int Uart_Disable_Irq(struct uart_port *port, uart_irq_e interrupts)
+{
+ unsigned int ret;
+
+ ret = fh_uart_readl(port, REG_UART_IER);
+ ret &= ~interrupts;
+ fh_uart_writel(port, REG_UART_IER, ret);
+
+ return 0;
+}
+
+static inline int Uart_Enable_Irq(struct uart_port *port, uart_irq_e interrupts)
+{
+ unsigned int ret;
+
+ ret = fh_uart_readl(port, REG_UART_IER);
+ ret |= interrupts;
+ fh_uart_writel(port, REG_UART_IER, ret);
+
+ return 0;
+}
+
+static inline int Uart_Read_Control_Status(struct uart_port *port)
+{
+ return fh_uart_readl(port, REG_UART_USR);
+}
+
+static inline int Uart_Check_Busy(struct uart_port *port)
+{
+ int ret;
+
+ ret = Uart_Read_Control_Status(port);
+ if (ret & UART_STATUS_BUSY) {
+ printk(KERN_ERR "%s: uart is busy, ret: %d\n",
+ __func__, ret);
+ return UART_IS_BUSY;
+ }
+
+ return 0;
+}
+
+static inline int Uart_Fifo_Config(struct uart_port *port,
+ unsigned int fifo_ctrl)
+{
+ unsigned int ret;
+
+ fh_uart_writel(port, REG_UART_FCR, fifo_ctrl);
+ ret = fh_uart_readl(port, REG_UART_IIR);
+
+ if (ret & UART_FIFO_IS_ENABLE)
+ return UART_CONFIG_FIFO_OK;
+ else
+ return UART_CONFIG_FIFO_ERROR;
+}
+
+static inline int Uart_Set_Line_Control(struct uart_port *port,
+ unsigned int line_ctrl)
+{
+ unsigned int ret;
+
+ ret = Uart_Check_Busy(port);
+ if (ret)
+ return UART_IS_BUSY;
+
+ fh_uart_writel(port, REG_UART_LCR, line_ctrl);
+ return UART_CONFIG_LINE_OK;
+}
+
+static inline int Uart_Read_Line_Status(struct uart_port *port)
+{
+ return fh_uart_readl(port, REG_UART_LSR);
+}
+
+void Uart_Flush_Fifo(struct uart_port *port)
+{
+ fh_uart_writel(port, REG_UART_FCR,
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+}
+
+static inline int Uart_Set_Clock_Divisor(struct uart_port *port, unsigned int baud)
+{
+ u32 low, high;
+ u32 ret;
+
+ ret = 0;
+ low = baud & 0x00ff;
+ high = (baud & 0xff00) >> 8;
+
+ ret = Uart_Check_Busy(port);
+ if (ret)
+ return UART_IS_BUSY;
+
+ ret = fh_uart_readl(port, REG_UART_LCR);
+ // if DLAB not set
+ if (!(ret & UART_LCR_DLAB_POS)) {
+ ret |= UART_LCR_DLAB_POS;
+ fh_uart_writel(port, REG_UART_LCR, ret);
+ }
+ /* fh_uart_writel(port, REG_UART_DLF, fraction_divide); */
+ fh_uart_writel(port, REG_UART_DLL, low);
+ fh_uart_writel(port, REG_UART_DLH, high);
+
+ /* clear DLAB */
+ ret = ret & 0x7f;
+ fh_uart_writel(port, REG_UART_LCR, ret);
+
+ return 0;
+}
+
+static inline int Uart_Read_iir(struct uart_port *port)
+{
+ return fh_uart_readl(port, REG_UART_IIR);
+}
+
+static bool fh_uart_dma_chan_filter(struct dma_chan *chan, void *param)
+{
+ int dma_channel = *(int *) param;
+ bool ret = false;
+
+ if (chan->chan_id == dma_channel)
+ ret = true;
+ return ret;
+}
+
+#ifdef CONFIG_UART_TX_DMA
+static void fh_serial_dma_tx_char_done(void *arg)
+{
+ struct uart_port *uart_port = (struct uart_port *)arg;
+ struct fh_uart_dma *dma_info = uart_dma[uart_port->line];
+
+ uart_port->icount.tx += dma_info->tx_count;
+ dma_info->tx_done = 1;
+}
+#endif
+
+static void fh_serial_dma_rx_char(void *arg)
+{
+ struct uart_port *port = (struct uart_port *)arg;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+ unsigned int uerstat;
+ unsigned int flag;
+ unsigned int xmit_len;
+ unsigned int i;
+
+ xmit_len = dma_info->rx_xmit_len;
+ port->icount.rx += xmit_len;
+ uerstat = Uart_Read_Line_Status(port);
+ flag = TTY_NORMAL;
+
+ if (unlikely(uerstat & UART_LINE_STATUS_RFE)) {
+ dev_dbg(port->dev, "rxerr: port rxs=0x%08x\n", uerstat);
+ if (uerstat & UART_LINE_STATUS_BI) {
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ goto dma_ignore_char;
+ }
+ }
+ if (uerstat & UART_LINE_STATUS_PE)
+ port->icount.parity++;
+ if (uerstat & UART_LINE_STATUS_BI)
+ port->icount.frame++;
+ if (uerstat & UART_LINE_STATUS_OE)
+ port->icount.overrun++;
+ uerstat &= port->read_status_mask;
+ if (uerstat & UART_LINE_STATUS_BI)
+ flag = TTY_BREAK;
+ else if (uerstat & UART_LINE_STATUS_PE)
+ flag = TTY_PARITY;
+ else if (uerstat & (UART_LINE_STATUS_FE |
+ UART_LINE_STATUS_OE))
+ flag = TTY_FRAME;
+ for (i = 0;
+ i < xmit_len; i++) {
+ if (!uart_handle_sysrq_char(port, dma_info->rx_dumy_buff[i])) {
+ uart_insert_char(port, uerstat, UART_LINE_STATUS_OE,\
+ dma_info->rx_dumy_buff[i], flag);
+ }
+ }
+
+dma_ignore_char:
+ tty_flip_buffer_push(&port->state->port);
+}
+
+static int uart_dma_set_rx_para(struct uart_port *port,
+ int xfer_len,
+ void (*call_back)(void *arg))
+{
+ struct fh_dma_extra ext_para;
+ struct dma_slave_config *rx_config;
+ struct dma_chan *rxchan;
+ struct scatterlist *p_sca_list;
+ unsigned int sg_size = 1;
+ struct dma_async_tx_descriptor *p_desc;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+
+ p_desc = 0;
+ memset(&dma_info->dma_rx.cfg,
+ 0,
+ sizeof(struct dma_slave_config));
+ memset(&ext_para, 0, sizeof(struct fh_dma_extra));
+ p_sca_list = &dma_info->dma_rx.sgl[0];
+ rxchan = dma_info->dma_rx.chan;
+ rx_config = &dma_info->dma_rx.cfg;
+ rx_config->src_addr = dma_info->paddr + REG_UART_RBR;
+ rx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ rx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ rx_config->slave_id = dma_info->rx_hs_no;
+ rx_config->src_maxburst = 16;
+ rx_config->dst_maxburst = 16;
+ rx_config->direction = DMA_DEV_TO_MEM;
+ rx_config->device_fc = 0;
+ ext_para.sinc = FH_DMA_SLAVE_FIX;
+ p_sca_list->dma_address = dma_info->rx_dma_add;
+ p_sca_list->length = min(xfer_len, 128);
+ ext_para.dinc = FH_DMA_SLAVE_INC;
+ dmaengine_slave_config(rxchan, rx_config);
+ p_desc =
+ rxchan->device->device_prep_slave_sg(rxchan,
+ &dma_info->dma_rx.sgl[0], sg_size, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT,
+ &ext_para);
+
+ dma_info->dma_rx.actual_sgl_size = sg_size;
+ p_desc->callback = fh_serial_dma_rx_callback;
+ p_desc->callback_param = port;
+ dma_info->dma_rx.desc = p_desc;
+
+ return 0;
+}
+
+void uart_unmap_dma_rx_sg(struct uart_port *port)
+{
+ struct dma_chan *rxchan;
+ struct scatterlist *p_sca_list;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+
+ p_sca_list = &dma_info->dma_rx.sgl[0];
+ rxchan = dma_info->dma_rx.chan;
+
+ dma_unmap_single(rxchan->dev->device.parent,
+ p_sca_list->dma_address,
+ 1,
+ DMA_FROM_DEVICE);
+}
+
+
+static void fh_serial_dma_rx_callback(void *arg)
+{
+ struct uart_port *port = (struct uart_port *)arg;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+
+ uart_unmap_dma_rx_sg(port);
+ fh_serial_dma_rx_char(port);
+
+ complete(&dma_info->rx_cmp);
+}
+
+#ifdef CONFIG_UART_TX_DMA
+static int uart_dma_set_tx_para(struct uart_port *port,
+ int xfer_len,
+ void (*call_back)(void *arg))
+{
+ struct fh_dma_extra ext_para;
+ struct dma_slave_config *tx_config;
+ struct dma_chan *txchan;
+ struct scatterlist *p_sca_list;
+ unsigned int sg_size = 1;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+
+ memset(&dma_info->dma_tx.cfg,
+ 0,
+ sizeof(struct dma_slave_config));
+ memset(&ext_para, 0, sizeof(struct fh_dma_extra));
+ p_sca_list = &dma_info->dma_tx.sgl[0];
+ txchan = dma_info->dma_tx.chan;
+ tx_config = &dma_info->dma_tx.cfg;
+ tx_config->dst_addr = dma_info->paddr + REG_UART_THR;
+ tx_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ tx_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ tx_config->slave_id = dma_info->tx_hs_no;
+ tx_config->src_maxburst = 1;
+ tx_config->dst_maxburst = 1;
+ tx_config->direction = DMA_MEM_TO_DEV;
+ tx_config->device_fc = 0;
+ ext_para.sinc = FH_DMA_SLAVE_FIX;
+ p_sca_list->dma_address = dma_map_single(
+ dma_info->dma_rx.chan->dev->device.parent,
+ (void *)dma_info->rx_dumy_buff,
+ sizeof(dma_info->rx_dumy_buff),
+ DMA_TO_DEVICE);
+ p_sca_list->length = min(xfer_len, 128);
+ ext_para.dinc = FH_DMA_SLAVE_INC;
+ dmaengine_slave_config(txchan, tx_config);
+ dma_info->dma_tx.desc =
+ txchan->device->device_prep_slave_sg(txchan,
+ &dma_info->dma_tx.sgl[0], sg_size, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
+ &ext_para);
+ dma_info->dma_tx.actual_sgl_size = sg_size;
+ dma_info->dma_tx.desc->callback = fh_serial_dma_tx_char_done;
+ dma_info->dma_tx.desc->callback_param = port;
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_UART_TX_DMA
+static void fh_serial_dma_tx_char(struct uart_port *port)
+{
+ unsigned int xfer_len;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+ struct circ_buf *xmit = &port->state->xmit;
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ dma_info->tx_done = 1;
+ dma_info->tx_done = 0;
+ return;
+ }
+
+ if (dma_info->tx_done) {
+ xfer_len =
+ uart_circ_chars_pending(xmit); /* Check xfer length */
+ if (xfer_len > 128)
+ xfer_len = 128;
+ if (xmit->tail < xmit->head) {
+ memcpy(dma_info->tx_dumy_buff,
+ &xmit->buf[xmit->tail],
+ xfer_len);
+ } else {
+ int first = UART_XMIT_SIZE - xmit->tail;
+ int second = xmit->head;
+
+ memcpy(dma_info->tx_dumy_buff,
+ &xmit->buf[xmit->tail],
+ first);
+ if (second)
+ memcpy(&dma_info->tx_dumy_buff[first],
+ &xmit->buf[0],
+ second);
+ }
+ xmit->tail = (xmit->tail + xfer_len) & (UART_XMIT_SIZE - 1);
+ dma_info->tx_count = xfer_len;
+ uart_dma_set_tx_para(
+ port,
+ xfer_len,
+ fh_serial_dma_tx_char_done);
+ dma_info->dma_tx.desc->tx_submit(dma_info->dma_tx.desc);
+ dma_info->tx_done = 0;
+ }
+}
+#endif
+
+int uart_rx_thread(void *data)
+{
+ struct uart_port *port = (struct uart_port *)data;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+
+ while (1) {
+ uart_dma_set_rx_para(port,
+ dma_info->rx_xmit_len,
+ fh_serial_dma_rx_callback);
+ dma_info->dma_rx.desc->tx_submit(dma_info->dma_rx.desc);
+
+ wait_for_completion(&dma_info->rx_cmp);
+ }
+}
+
+int fh_uart_rx_dma_start(struct uart_port *port)
+{
+ struct task_struct *uart_rx_kthread = NULL;
+ int err = 0;
+ char thread_name[16] = {0};
+
+ sprintf(thread_name, "uart%d_rx", port->line);
+
+ uart_rx_kthread = kthread_create(uart_rx_thread,
+ port,
+ thread_name);
+
+ if (IS_ERR(uart_rx_kthread)) {
+ pr_err("Create UART DMA RX Thread Failed!\n");
+ err = PTR_ERR(uart_rx_kthread);
+ uart_rx_kthread = NULL;
+
+ return err;
+ }
+
+ wake_up_process(uart_rx_kthread);
+
+ return err;
+}
+
+
+static inline int Uart_Init(struct uart_port *port)
+{
+ int ret = 0;
+ unsigned int quot;
+
+ Uart_Flush_Fifo(port);
+ quot = ((port->uartclk / UART_DEFAULT_BAUD) + 8) / 16;
+ ret |= Uart_Set_Clock_Divisor(port, quot);
+ ret |= Uart_Set_Line_Control(port, UART_LINE);
+ if (uart_dma[port->line])
+ ret |= Uart_Fifo_Config(port, UART_INT_RXFIFO_DEPTH_QUARTER_DMA);
+ else
+ ret |= Uart_Fifo_Config(port, UART_FIFO);
+ Uart_Disable_Irq(port, UART_INT_ALL);
+ if (uart_dma[port->line] && !uart_dma[port->line]->inited) {
+ uart_dma[port->line]->inited = 1;
+ ret |= fh_uart_rx_dma_start(port);
+ } else
+ fh_serial_start_rx(port);
+
+
+ return ret;
+}
+
+static irqreturn_t
+fh_uart_rx_chars(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ unsigned int ch = 0;
+ unsigned int flag;
+ unsigned int uerstat;
+ int max_count = 64;
+ int ret_status;
+
+ while (max_count-- > 0) {
+ //check if rx fifo is empty
+ ret_status = Uart_Read_Control_Status(port);
+ //0 means empty. 1 means not empty
+ if (!(ret_status & UART_STATUS_RFNE))
+ break;
+ //read error in the rx process
+ uerstat = Uart_Read_Line_Status(port);
+ //read data in the rxfifo
+ if (uerstat & UART_LINE_STATUS_DR)
+ ch = fh_uart_readl(port, REG_UART_RBR);
+ /* insert the character into the buffer */
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+ //if at least one error in rx process
+ if (unlikely(uerstat & UART_LINE_STATUS_RFE)) {
+ dev_dbg(port->dev, "rxerr: port ch=0x%02x, rxs=0x%08x\n",
+ ch, uerstat);
+ /* check for break */
+ if (uerstat & UART_LINE_STATUS_BI) {
+ //dbg("break!\n");
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ goto ignore_char;
+ }
+
+ if (uerstat & UART_LINE_STATUS_BI)
+ port->icount.frame++;
+ if (uerstat & UART_LINE_STATUS_OE)
+ port->icount.overrun++;
+
+ //check the mask
+ uerstat &= port->read_status_mask;
+
+ if (uerstat & UART_LINE_STATUS_BI)
+ flag = TTY_BREAK;
+ else if (uerstat & UART_LINE_STATUS_PE)
+ flag = TTY_PARITY;
+ else if (uerstat & (UART_LINE_STATUS_FE |
+ UART_LINE_STATUS_OE))
+ flag = TTY_FRAME;
+ }
+
+ if (uart_handle_sysrq_char(port, ch))
+ goto ignore_char;
+
+ uart_insert_char(port, uerstat, UART_LINE_STATUS_OE,
+ ch, flag);
+
+ignore_char:
+ continue;
+ }
+ tty_flip_buffer_push(&port->state->port);
+ return IRQ_HANDLED;
+}
+
+
+
+static irqreturn_t
+fh_uart_tx_chars(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ struct circ_buf *xmit = &port->state->xmit;
+ int count = 256;
+ int ret_status;
+
+ /* if there isn't anything more to transmit, or the uart is now
+ * stopped, disable the uart and exit
+ */
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ fh_serial_stop_tx(port);
+ goto out;
+ }
+ /* try and drain the buffer... */
+ while (!uart_circ_empty(xmit) && count-- > 0) {
+
+ //check the tx fifo full? full then break
+ ret_status = Uart_Read_Control_Status(port);
+ if (!(ret_status & UART_STATUS_TFNF)) //0 means full. 1 means not full
+ break;
+ //write data to the hw fifo
+ fh_uart_writel(port, REG_UART_THR, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ fh_serial_stop_tx(port);
+out:
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+fh_uart_isr(int irq, void *dev_id)
+{
+ irqreturn_t ret_isr;
+ struct uart_port *port = dev_id;
+ int ret_iir;
+ int control_status;
+ int line_status;
+
+ ret_iir = Uart_Read_iir(port);
+
+ ret_iir = ret_iir & 0xf;
+
+ if (ret_iir == 0xc) {
+ control_status = Uart_Read_Control_Status(port);
+
+ if (!(control_status & UART_STATUS_RFNE)) {
+ line_status = Uart_Read_Line_Status(port);
+
+ if (!(line_status & UART_LINE_STATUS_DR)) {
+ fh_uart_readl(port, REG_UART_RBR);
+ return IRQ_HANDLED;
+ }
+ }
+ }
+
+ if ((ret_iir & 0x04))
+ ret_isr = fh_uart_rx_chars(irq, dev_id);
+
+ if (ret_iir & 0x02)
+ ret_isr = fh_uart_tx_chars(irq, dev_id);
+ else
+ ret_isr = IRQ_HANDLED;
+
+ return ret_isr;
+}
+
+static void fh_serial_stop_tx(struct uart_port *port)
+{
+ if (uart_dma[port->line]) {
+ struct circ_buf *xmit = &port->state->xmit;
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+
+ xmit->tail =
+ (xmit->tail + dma_info->tx_count) & (UART_XMIT_SIZE - 1);
+ port->icount.tx += dma_info->tx_count;
+ dma_info->tx_count = 0;
+ dma_info->tx_done = 1;
+ }
+
+ Uart_Disable_Irq(port, UART_INT_ETBEI_POS);
+}
+
+static void fh_serial_start_tx(struct uart_port *port)
+{
+#ifdef CONFIG_UART_TX_DMA
+ if (uart_dma[port->line]) {
+ struct fh_uart_dma *dma_info = uart_dma[port->line];
+
+ if (dma_info->tx_done)
+ fh_serial_dma_tx_char(port);
+ } else
+#endif
+ Uart_Enable_Irq(port, UART_INT_ETBEI_POS);
+}
+
+static void fh_serial_stop_rx(struct uart_port *port)
+{
+ Uart_Disable_Irq(port, UART_INT_ERBFI_POS);
+}
+
+static void fh_serial_start_rx(struct uart_port *port)
+{
+ Uart_Enable_Irq(port, UART_INT_ERBFI_POS);
+}
+
+static unsigned int fh_serial_tx_empty(struct uart_port *port)
+{
+ /*//1 means empty 0:means no empty*/
+ int ret;
+ int ret_status;
+
+ ret_status = Uart_Read_Control_Status(port);
+ if (ret_status & UART_STATUS_TFE)
+ ret = 1;
+ else
+ ret = 0;
+ return ret;
+}
+
+static unsigned int fh_serial_get_mctrl(struct uart_port *port)
+{
+ /* The FH UART handles flow control in hardware */
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+
+static void fh_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* The FH UART handles flow control in hardware */
+}
+
+static void fh_serial_break_ctl(struct uart_port *port, int break_state)
+{
+ /* We don't support sending break */
+}
+
+static void fh_serial_shutdown(struct uart_port *port)
+{
+ Uart_Disable_Irq(port, UART_INT_ALL);
+ Uart_Flush_Fifo(port);
+ free_irq(port->irq, port);
+}
+
+static int fh_serial_startup(struct uart_port *port)
+{
+ int ret;
+ int status;
+ char *isr_name;
+
+ do {
+ status = Uart_Read_Line_Status(port);
+ } while ((status & UART_FIFO_BOTH_EMPTY) != UART_FIFO_BOTH_EMPTY);
+
+ Uart_Init(port);
+
+ isr_name = kzalloc(16, GFP_KERNEL);
+ sprintf(isr_name, "ttyS-%d", port->line);
+
+ ret = request_irq(port->irq, fh_uart_isr, 0,
+ isr_name, port);
+ if (ret) {
+ printk(KERN_ERR "request serial irq %d failed.\n", port->irq);
+ return ret;
+ }
+
+ enable_irq_wake(port->irq);
+
+ return 0;
+}
+
+static void fh_serial_set_termios(struct uart_port *port,
+ struct ktermios *termios,
+ struct ktermios *old)
+{
+ unsigned long flags;
+ unsigned int baud, quot;
+ unsigned int line_data = 0, status;
+
+ do {
+ status = Uart_Read_Line_Status(port);
+
+ } while ((status & UART_FIFO_BOTH_EMPTY) != UART_FIFO_BOTH_EMPTY);
+ //data bit
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ line_data |= UART_LCR_WLEN5; //5bit
+ break;
+ case CS6:
+ line_data |= UART_LCR_WLEN6; //6bit
+ break;
+ case CS7:
+ line_data |= UART_LCR_WLEN7; //7bit
+ break;
+ case CS8:
+ line_data |= UART_LCR_WLEN8; //8bit
+ break;
+ default:
+ line_data |= UART_LCR_WLEN8;
+ break;
+ }
+ /* stop bits */
+ if (termios->c_cflag & CSTOPB)
+ line_data |= UART_LCR_STOP; //0:1bit 1:2bit
+ //parity enable?
+ if (termios->c_cflag & PARENB) {
+ line_data |= UART_LCR_PARITY;
+ //even or odd parity
+ if (!(termios->c_cflag & PARODD))
+ line_data |= UART_LCR_EPAR;
+ }
+ //baud cal. baud is the uart will be out. the quot is the div
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+ quot = uart_get_divisor(port, baud);
+
+ do {
+ status = Uart_Read_Line_Status(port);
+ } while ((status & UART_FIFO_BOTH_EMPTY) != UART_FIFO_BOTH_EMPTY);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+ spin_lock_irqsave(&port->lock, flags);
+
+ port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= UART_LSR_BI;
+
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= UART_LSR_BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= UART_LSR_OE;
+ }
+
+ /*
+ * ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= UART_LSR_DR;
+
+ Uart_Flush_Fifo(port);
+ Uart_Set_Clock_Divisor(port, quot);
+ Uart_Set_Line_Control(port, line_data);
+ Uart_Disable_Irq(port, UART_INT_ALL);
+
+ if (!uart_dma[port->line]) {
+ Uart_Fifo_Config(port, UART_FIFO);
+ fh_serial_start_rx(port);
+ } else
+ Uart_Fifo_Config(port, UART_INT_RXFIFO_DEPTH_QUARTER_DMA);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+
+
+static const char *fh_serial_type(struct uart_port *port)
+{
+ return (port->type == PORT_FH) ? FH_DRIVE_NAME : NULL;
+}
+
+static void fh_serial_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase, MAP_SIZE);
+}
+
+static int fh_serial_request_port(struct uart_port *port)
+{
+ return request_mem_region(port->mapbase, MAP_SIZE, FH_SERIAL_NAME) ? 0 : -EBUSY;
+}
+
+
+static void fh_serial_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ fh_serial_request_port(port);
+ port->type = PORT_FH;
+ }
+}
+
+static int fh_serial_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ int ret = 0;
+
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_FH)
+ ret = -EINVAL;
+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ ret = -EINVAL;
+ if (ser->baud_base < 2400)
+ ret = -EINVAL;
+ return ret;
+}
+
+/*********************************
+ *
+ *FH Memory Debug
+ *
+ ********************************/
+#ifdef CONFIG_MAGIC_SYSRQ
+
+static void SysrqShowCharacter(char *character)
+{
+ struct uart_port *port;
+
+ port = &fh_serial_ports[0];
+
+ fh_uart_writel(port, REG_UART_THR, *character);
+}
+
+static unsigned int SysrqParseHex(char *buff)
+{
+ unsigned int data;
+
+ data = (unsigned int)simple_strtoul(buff, NULL, 16);
+ return data;
+}
+
+static void SysrqGetCharacter(char *buff)
+{
+ struct uart_port *port;
+ char ch;
+
+ port = &fh_serial_ports[0];
+ while (1) {
+ if ((fh_uart_readl(port, REG_UART_LSR) & 0x01) == 0x01) {
+ ch = fh_uart_readl(port, REG_UART_RBR) & 0xff;
+ SysrqShowCharacter(&ch);
+ if (ch == ' ' || ch == '\r' || ch == '\n')
+ break;
+ else
+ *buff++ = ch;
+ }
+ }
+}
+
+static int SysrqGetDirection(void)
+{
+ char ch;
+
+ SysrqGetCharacter(&ch);
+ if (ch == 'w' || ch == 'W')
+ return 1;
+ else if (ch == 'r' || ch == 'R')
+ return 0;
+ else
+ return -1;
+}
+
+static int SysrqGetMode(void)
+{
+ char ch;
+
+ SysrqGetCharacter(&ch);
+ if (ch == 'v' || ch == 'V')
+ return 1;
+ else if (ch == 'p' || ch == 'P')
+ return 0;
+ else
+ return -1;
+}
+
+static void SysWritePhyMemory(int phyaddress, int value)
+{
+ int virtualaddress;
+
+ pr_info("Physical Address Write:0x%08x->0x%08x", value, phyaddress);
+ virtualaddress = __phys_to_virt(phyaddress);
+ writel(value, (void __iomem *)virtualaddress);
+}
+
+static void SysWriteVirtualMemory(int virtualaddress, int value)
+{
+ pr_info("Virtual Address Write:0x%08x->0x%08x", value, virtualaddress);
+
+ writel(value, (void __iomem *)virtualaddress);
+}
+
+static void SysWriteMemory(void)
+{
+ int mode;
+ int address;
+ int value;
+ char internal_buffer[11] = {0};
+
+ mode = SysrqGetMode();
+ switch (mode) {
+ case 0:
+ SysrqGetCharacter(internal_buffer);
+ address = SysrqParseHex(internal_buffer);
+ memset(internal_buffer, 0, sizeof(internal_buffer));
+ SysrqGetCharacter(internal_buffer);
+ value = SysrqParseHex(internal_buffer);
+ SysWritePhyMemory(address, value);
+ break;
+ case 1:
+ SysrqGetCharacter(internal_buffer);
+ address = SysrqParseHex(internal_buffer);
+ memset(internal_buffer, 0, sizeof(internal_buffer));
+ SysrqGetCharacter(internal_buffer);
+ value = SysrqParseHex(internal_buffer);
+ SysWriteVirtualMemory(address, value);
+ break;
+ default:
+ pr_info("Select Wrong Mode\n");
+ break;
+ }
+}
+
+static void SysReadPhyMemory(int phyaddress, int length)
+{
+ int start;
+ int virtualaddress;
+ unsigned int ch;
+
+ pr_info("Physical Address Read From:0x%08x(0x%x)\n", phyaddress, length);
+ virtualaddress = __phys_to_virt(phyaddress);
+ for (start = 0; start < length; start++) {
+ if (start % 8 == 0)
+ pr_info("Address:%02x:\n", (virtualaddress + start * 4) & 0xff);
+ ch = readl((void __iomem *)(virtualaddress + start * 4));
+ pr_info("0x%08x \n", ch);
+ }
+}
+
+static void SysReadVirtualMemory(int virtualaddress, int length)
+{
+ int start;
+ unsigned int ch;
+
+ pr_info("Virtual Address Read From:0x%08x(0x%x)\n", virtualaddress, length);
+ for (start = 0; start < length; start++) {
+ if (start % 8 == 0)
+ pr_info("Address:%08x:\n", (virtualaddress + start * 4));
+ ch = readl((void __iomem *)(virtualaddress + start * 4));
+ pr_info("0x%08x \n", ch);
+ }
+}
+
+
+static void SysReadMemory(void)
+{
+ int mode;
+ int address;
+ int length;
+ char internal_buffer[11] = {0};
+
+ mode = SysrqGetMode();
+ switch (mode) {
+ case 0:
+ SysrqGetCharacter(internal_buffer);
+ address = SysrqParseHex(internal_buffer);
+ memset(internal_buffer, 0, sizeof(internal_buffer));
+ SysrqGetCharacter(internal_buffer);
+ length = SysrqParseHex(internal_buffer);
+ SysReadPhyMemory(address, length);
+ break;
+ case 1:
+ SysrqGetCharacter(internal_buffer);
+ address = SysrqParseHex(internal_buffer);
+ memset(internal_buffer, 0, sizeof(internal_buffer));
+ SysrqGetCharacter(internal_buffer);
+ length = SysrqParseHex(internal_buffer);
+ SysReadVirtualMemory(address, length);
+ break;
+ default:
+ pr_info("Select Wrong Mode\n");
+ break;
+ }
+}
+
+static void SysHandleFHMemory(int key)
+{
+ int direction;
+
+ direction = SysrqGetDirection();
+ switch (direction) {
+ case 0:
+ SysReadMemory();
+ break;
+ case 1:
+ SysWriteMemory();
+ break;
+ default:
+ pr_info("Select Wrong Direction\n");
+ break;
+ }
+}
+
+#endif
+
+/*********************************
+ *
+ *
+ * FH CONSOLE
+ *
+ *
+ *********************************/
+static void
+fh_serial_console_putchar(struct uart_port *port, int ch)
+{
+ unsigned int ret;
+
+ do {
+ ret = Uart_Read_Control_Status(port);
+ }
+ //wait txfifo is full
+ //0 means full. 1 means not full
+ while (!(ret & UART_STATUS_TFNF))
+ ;
+
+ fh_uart_writel(port, REG_UART_THR, ch);
+}
+
+static void
+fh_serial_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ struct uart_port *port;
+
+ if (co->index < 0)
+ return;
+
+ port = &fh_serial_ports[co->index];
+ uart_console_write(port, s, count, fh_serial_console_putchar);
+}
+
+
+static int __init
+fh_serial_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+ /* is this a valid port */
+ if (co->index < 0 || co->index >= FH_UART_NUMBER) {
+ pr_err("ERROR: co->index invaild: %d\n", co->index);
+ return -EINVAL;
+ }
+
+ port = &fh_serial_ports[co->index];
+ /* Console First Initialize */
+#ifdef CONFIG_USE_OF
+ fh_serial_of_configure();
+#else
+ port->ops = &fh_serial_ops;
+#endif
+
+ /* is the port configured? */
+ if (port->mapbase == 0x0)
+ pr_err("ERROR: port->mapbase == 0x0\n");
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ uart_set_options(port, co, baud, parity, bits, flow);
+
+ // must true for setup ok, see printk.c line:1463
+ return 1;
+}
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static struct sysrq_key_op sysrq_fh_debug_mem_op = {
+ .handler = SysHandleFHMemory,
+ .help_msg = "Fullhan Debug Dump Mem(G)",
+ .action_msg = "Fullhan Dump Mem(w or r)",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
+};
+#endif
+
+static int fh_serial_probe(struct platform_device *op)
+{
+ struct uart_port *port = NULL;
+ struct clk *uart_clk = NULL;
+ char clk_name[16] = {0};
+ int ret, id;
+
+#ifdef CONFIG_USE_OF
+ id = of_alias_get_id(op->dev.of_node, "ttyS");
+#else
+ id = op->id;
+#endif
+ port = &fh_serial_ports[id];
+ ret = fh_serial_configure(port, op);
+ if (ret < 0) {
+ pr_info("fh serial driver probe fail.\n");
+ return -EIO;
+ }
+
+ sprintf(clk_name, "uart%d_clk", id);
+ uart_clk = clk_get(NULL, clk_name);
+ if (!IS_ERR(uart_clk)) {
+ ret = clk_prepare_enable(uart_clk);
+ if (ret)
+ return ret;
+ }
+
+ port->dev = &op->dev;
+
+ uart_add_one_port(&fh_serial_driver, (struct uart_port *)port);
+
+#ifdef CONFIG_MAGIC_SYSRQ
+ register_sysrq_key('g', &sysrq_fh_debug_mem_op);
+#endif
+ pr_info("fh serial at 0x%x, irq %d\n",
+ (resource_size_t) port->mapbase, port->irq);
+ return 0;
+}
+
+static int fh_serial_remove(struct platform_device *op)
+{
+ /* This will never be called */
+ struct uart_port *port = dev_get_drvdata(&op->dev);
+
+ if (port)
+ uart_remove_one_port(&fh_serial_driver, port);
+
+ return 0;
+}
+
+#ifdef CONFIG_USE_OF
+static struct of_device_id fh_serial_match[] = {
+ {
+ .compatible = "fh,fh-serial",
+ },
+ {},
+};
+#endif
+
+static struct platform_driver fh_serial_of_driver = {
+ .probe = fh_serial_probe,
+ .remove = fh_serial_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = FH_DRIVE_NAME,
+#ifdef CONFIG_USE_OF
+ .of_match_table = fh_serial_match,
+#endif
+ },
+};
+
+#ifndef CONFIG_USE_OF
+static struct early_platform_driver early_fh_uart_driver __initdata = {
+ .class_str = "fh-console",
+ .pdrv = &fh_serial_of_driver,
+ .requested_id = EARLY_PLATFORM_ID_UNSET,
+};
+#endif
+
+static int __init fh_serial_initconsole(void)
+{
+#ifndef CONFIG_USE_OF
+ int ret = 0;
+
+ ret = early_platform_driver_register(&early_fh_uart_driver, FH_DRIVE_NAME);
+
+ ret = early_platform_driver_probe("fh-console", FH_UART_NUMBER, 0);
+#endif
+ register_console(&fh_serial_console);
+ return 0;
+}
+console_initcall(fh_serial_initconsole);
+
+
+static struct console fh_serial_console = {
+ .name = FH_DEV_NAME,
+ .device = uart_console_device,
+ .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_ENABLED, //CON_ENABLED for ttys1 for 81
+ .index = -1,
+ .write = fh_serial_console_write,
+ .setup = fh_serial_console_setup,
+ .data = &fh_serial_driver,
+};
+
+#ifdef CONFIG_USE_OF
+static int fh_serial_of_configure(void)
+{
+ struct device_node *np;
+ int line;
+
+ for_each_matching_node(np, fh_serial_match) {
+ unsigned int irq, freq_hz, fifo_size, regs;
+ struct uart_port *port;
+
+ irq = irq_of_parse_and_map(np, 0);
+ line = of_alias_get_id(np, "ttyS");
+
+ of_property_read_u32(np, "reg", &regs);
+ of_property_read_u32(np, "clock-frequency", &freq_hz);
+ of_property_read_u32(np, "fifo_size", &fifo_size);
+
+ port = &fh_serial_ports[line];
+ port->mapbase = regs;
+ port->membase = ioremap(regs, MAP_SIZE);
+ port->irq = irq;
+ port->iotype = UPIO_MEM;
+ port->ops = &fh_serial_ops;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->line = line;
+ port->uartclk = freq_hz;
+ port->fifosize = fifo_size;
+
+ /* We support maximum UART_NR uarts ... */
+ if (line == FH_UART_NUMBER)
+ break;
+ }
+
+ return line ? 0 : -ENODEV;
+}
+#endif
+
+static int fh_serial_configure(struct uart_port *port, struct platform_device *op)
+{
+#ifdef CONFIG_USE_OF
+ const struct of_device_id *match;
+ struct device_node *np = op->dev.of_node;
+ unsigned int irq, freq_hz, fifo_size, regs;
+
+ match = of_match_device(fh_serial_match, &op->dev);
+ if (!match) {
+ pr_info("Invalid uart device mismatch.\n");
+ return -ENODEV;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ of_property_read_u32(np, "reg", &regs);
+ of_property_read_u32(np, "clock-frequency", &freq_hz);
+ of_property_read_u32(np, "fifo-size", &fifo_size);
+
+ port->mapbase = regs;
+ port->membase = of_iomap(np, 0);
+ port->irq = irq;
+ port->iotype = UPIO_MEM;
+ port->ops = &fh_serial_ops;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->line = of_alias_get_id(op->dev.of_node, "ttyS");
+ port->uartclk = freq_hz;
+ port->fifosize = fifo_size;
+
+ return of_alias_get_id(op->dev.of_node, "ttyS");
+#else
+ struct fh_platform_uart *plat_data = dev_get_platdata(&op->dev);
+ int filter_no;
+ dma_cap_mask_t mask;
+
+ if (op->id < 0 || op->id >= FH_UART_NUMBER) {
+ pr_err("Invalid uart platform device id.\n");
+ return -ENOENT;
+ }
+
+ port->mapbase = plat_data->mapbase;
+ port->membase = ioremap(plat_data->mapbase, SZ_4K);
+ port->irq = irq_create_mapping(NULL, plat_data->irq);
+ port->iotype = UPIO_MEM;
+ port->ops = &fh_serial_ops;
+ port->flags = UPF_BOOT_AUTOCONF;
+ port->line = op->id;
+ port->uartclk = plat_data->uartclk;
+ port->fifosize = plat_data->fifo_size;
+
+ if (plat_data->use_dma) {
+ struct fh_uart_dma *dma_info = plat_data->dma_info;
+
+ dma_info->paddr = plat_data->mapbase;
+
+#ifdef CONFIG_UART_TX_DMA
+ filter_no = dma_info->tx_dma_channel;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_info->dma_tx.chan = dma_request_channel(mask,
+ fh_uart_dma_chan_filter, &filter_no);
+ if (!dma_info->dma_tx.chan) {
+ op->id = -1;
+ goto out;
+ }
+#endif
+
+ filter_no = dma_info->rx_dma_channel;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_info->dma_rx.chan = dma_request_channel(mask,
+ fh_uart_dma_chan_filter, &filter_no);
+ if (!dma_info->dma_rx.chan) {
+ dma_release_channel(dma_info->dma_tx.chan);
+ op->id = -1;
+ goto out;
+ }
+
+#ifdef CONFIG_UART_TX_DMA
+ dma_info->tx_dma_add = dma_map_single(
+ dma_info->dma_tx.chan->dev->device.parent,
+ (void *)dma_info->tx_dumy_buff,
+ sizeof(dma_info->tx_dumy_buff),
+ DMA_TO_DEVICE);
+#endif
+ dma_info->rx_dma_add = dma_map_single(
+ dma_info->dma_rx.chan->dev->device.parent,
+ (void *)dma_info->rx_dumy_buff,
+ sizeof(dma_info->rx_dumy_buff),
+ DMA_TO_DEVICE);
+
+ dma_info->tx_done = 1;
+ dma_info->tx_count = 0;
+ init_completion(&dma_info->rx_cmp);
+
+ uart_dma[op->id] = dma_info;
+ }
+
+out:
+ return op->id;
+#endif
+}
+
+static int __init fh_serial_init(void)
+{
+ int ret;
+ /* Find all UARTS in device the tree and initialize their ports */
+
+ pr_info("Serial: fh serial driver\n");
+
+ ret = uart_register_driver(&fh_serial_driver);
+
+ if (ret) {
+ pr_err("%s: uart_register_driver failed (%i)\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = platform_driver_register(&fh_serial_of_driver);
+ if (ret) {
+ pr_err("%s: platform_driver_register failed (%i)\n",
+ __func__, ret);
+ uart_unregister_driver(&fh_serial_driver);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void __exit fh_serial_exit(void)
+{
+ int i;
+
+ for (i = 0; i < FH_UART_NUMBER; i++)
+ uart_remove_one_port(&fh_serial_driver,
+ &fh_serial_ports[i]);
+
+ uart_unregister_driver(&fh_serial_driver);
+ platform_driver_unregister(&fh_serial_of_driver);
+}
+
+module_init(fh_serial_init);
+module_exit(fh_serial_exit);
+
+MODULE_AUTHOR("Fullhan Software Team");
+MODULE_DESCRIPTION("Fullhan Serial device driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/fh_serial.h b/drivers/tty/serial/fh_serial.h
new file mode 100644
index 00000000..5c0eb9f3
--- /dev/null
+++ b/drivers/tty/serial/fh_serial.h
@@ -0,0 +1,146 @@
+/*
+ * linux/drivers/tty/serial/fh_of_serial.h
+ *
+ * Copyright (C) 2017 Fullhan Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef FH_SERIAL_H_
+#define FH_SERIAL_H_
+
+
+#define lift_shift_bit_num(bit_num) (1<<bit_num)
+#define ISR_NUMBER0 (30)
+#define ISR_NUMBER1 (31)
+#define ISR_NUMBER2 (35)
+#define UART0_PORT 0
+#define UART1_PORT 1
+#define UART2_PORT 2
+#define UART_MAX_NUM 3
+#define UART_DATA_ARRIVED 1
+#define UART_LCR_DLAB_POS (lift_shift_bit_num(7))
+
+#define UART0_FIFO_SIZE 32
+#define UART1_FIFO_SIZE 16
+#define UART2_FIFO_SIZE 16
+
+/****************************************************************************
+ * ADT section
+ * add Abstract Data Type definition here
+ ***************************************************************************/
+/* error status */
+enum {
+ UART_CONFIG_OK = 0,
+ UART_CONFIG_FIFO_OK = 0,
+ UART_CONFIG_LINE_OK = 0,
+ UART_CONFIG_DIVISOR_OK = 0,
+ UART_WRITE_DATA_OK = 0,
+ UART_READ_DATA_OK = 0,
+ UART_CLEAR_ERROR_OK = 0,
+ UART_RESET_RX_POOL_OK = 0,
+ UART_CLEAR_RX_DATA_READY_OK = 0,
+ UART_INIT_OK = 0,
+ UART_CONFIG_PARA_ERROR = lift_shift_bit_num(0),
+ UART_CONFIG_FIFO_ERROR = lift_shift_bit_num(1),
+ UART_IS_BUSY = lift_shift_bit_num(2),
+ UART_DW_FIFO_OVERFLOW = lift_shift_bit_num(3), //dw rxfifo overflow ,maybe rxisr is closed or main clock is too low
+ UART_SW_FIFO_OVERFLOW = lift_shift_bit_num(4), //soft rxfifo overflow , maybe main clk is too low
+ UART_PARITY_ERROR = lift_shift_bit_num(5),
+ UART_FRAME_ERROR = lift_shift_bit_num(6),
+ UART_BREAK_ERROR = lift_shift_bit_num(7),
+ UART_FIFO_EMPTY = lift_shift_bit_num(8),
+};
+
+/* interrupt enable */
+typedef enum enum_uart_irq {
+ UART_INT_PTIME_POS = (lift_shift_bit_num(7)),
+ UART_INT_EDSSI_POS = (lift_shift_bit_num(3)),
+ UART_INT_ELSI_POS = (lift_shift_bit_num(2)),
+ UART_INT_ETBEI_POS = (lift_shift_bit_num(1)),
+ UART_INT_ERBFI_POS = (lift_shift_bit_num(0)),
+ UART_INT_ALL = 0x0f,
+}uart_irq_e;
+
+/* interrupt id */
+enum {
+ UART_INT_ID_MODEM = 0,
+ UART_INT_ID_NO_INT = 1,
+ UART_INT_ID_THR_EMPTY = 2,
+ UART_INT_ID_RECEIVE_DATA = 4,
+ UART_INT_ID_RECEIVE_LINE = 6,
+ UART_INT_ID_BUSY = 7,
+ UART_INT_ID_TIME_OUT = 12,
+ UART_FIFO_IS_ENABLE = 0xc0,
+};
+
+typedef enum enum_uart_line {
+ Uart_line_5n1 = 0x00, // 5 data bits, no parity, 1 stop bit
+ Uart_line_5n1_5 = 0x04, // 5 data bits, no parity, 1.5 stop bits
+ Uart_line_5e1 = 0x18, // 5 data bits, even parity, 1 stop bit
+ Uart_line_5e1_5 = 0x1c, // 5 data bits, even parity, 1.5 stop bits
+ Uart_line_5o1 = 0x08, // 5 data bits, odd parity, 1 stop bit
+ Uart_line_5o1_5 = 0x0c, // 5 data bits, odd parity, 1.5 stop bits
+ Uart_line_6n1 = 0x01, // 6 data bits, no parity, 1 stop bit
+ Uart_line_6n2 = 0x05, // 6 data bits, no parity, 2 stop bits
+ Uart_line_6e1 = 0x19, // 6 data bits, even parity, 1 stop bit
+ Uart_line_6e2 = 0x1d, // 6 data bits, even parity, 2 stop bits
+ Uart_line_6o1 = 0x09, // 6 data bits, odd parity, 1 stop bit
+ Uart_line_6o2 = 0x0d, // 6 data bits, odd parity, 2 stop bits
+ Uart_line_7n1 = 0x02, // 7 data bits, no parity, 1 stop bit
+ Uart_line_7n2 = 0x06, // 7 data bits, no parity, 2 stop bits
+ Uart_line_7e1 = 0x1a, // 7 data bits, even parity, 1 stop bit
+ Uart_line_7e2 = 0x1e, // 7 data bits, even parity, 2 stop bits
+ Uart_line_7o1 = 0x0a, // 7 data bits, odd parity, 1 stop bit
+ Uart_line_7o2 = 0x0e, // 7 data bits, odd parity, 2 stop bits
+ Uart_line_8n1 = 0x03, // 8 data bits, no parity, 1 stop bit
+ Uart_line_8n2 = 0x07, // 8 data bits, no parity, 2 stop bits
+ Uart_line_8e1 = 0x1b, // 8 data bits, even parity, 1 stop bit
+ Uart_line_8e2 = 0x1f, // 8 data bits, even parity, 2 stop bits
+ Uart_line_8o1 = 0x0b, // 8 data bits, odd parity, 1 stop bit
+ Uart_line_8o2 = 0x0f // 8 data bits, odd parity, 2 stop bits
+}uart_line_e;
+
+/* rx & tx fifo config */
+typedef enum enum_uart_fifo {
+ UART_INT_RXFIFO_DEPTH_1 = 0x01, //fifo enable, rx 1 byte, set rx int
+ UART_INT_RXFIFO_DEPTH_QUARTER = 0x41, //fifo enable, rx 1/4 fifo, set rx int
+ UART_INT_RXFIFO_DEPTH_QUARTER_DMA = 0x4F, //fifo enable, rx 1/4 fifo, set rx int&DMA
+ UART_INT_RXFIFO_DEPTH_HALF = 0x81, //fifo enable, rx 1/2 fifo, set rx int
+ UART_INT_RXFIFO_2LESS_THAN_FULL =0xc1, //fifo enable, rx 2 less than full, set rx int
+}uart_fifo_e;
+
+/* line status */
+enum {
+ UART_LINE_STATUS_RFE = (lift_shift_bit_num(7)),
+ UART_LINE_STATUS_TEMT = (lift_shift_bit_num(6)),
+ UART_LINE_STATUS_THRE = (lift_shift_bit_num(5)),
+ UART_LINE_STATUS_BI = (lift_shift_bit_num(4)),
+ UART_LINE_STATUS_FE = (lift_shift_bit_num(3)),
+ UART_LINE_STATUS_PE = (lift_shift_bit_num(2)),
+ UART_LINE_STATUS_OE = (lift_shift_bit_num(1)),
+ UART_LINE_STATUS_DR = (lift_shift_bit_num(0)),
+};
+
+//uart status
+enum {
+ UART_STATUS_RFF = (lift_shift_bit_num(4)),
+ UART_STATUS_RFNE = (lift_shift_bit_num(3)),
+ UART_STATUS_TFE = (lift_shift_bit_num(2)),
+ UART_STATUS_TFNF = (lift_shift_bit_num(1)),
+ UART_STATUS_BUSY = (lift_shift_bit_num(0)),
+
+};
+
+#endif /* FH_SERIAL_H_ */
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/fulltty_serial.c
similarity index 86%
rename from drivers/tty/serial/serial_core.c
rename to drivers/tty/serial/fulltty_serial.c
index 53e6db8b..2219e724 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/fulltty_serial.c
@@ -43,12 +43,6 @@
*/
static DEFINE_MUTEX(port_mutex);
-/*
- * lockdep: port->lock is initialized in two places, but we
- * want only one lock-class:
- */
-static struct lock_class_key port_lock_key;
-
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
@@ -298,183 +292,6 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
uart_port_unlock(uport, flags);
}
-/**
- * uart_update_timeout - update per-port FIFO timeout.
- * @port: uart_port structure describing the port
- * @cflag: termios cflag value
- * @baud: speed of the port
- *
- * Set the port FIFO timeout value. The @cflag value should
- * reflect the actual hardware settings.
- */
-void
-uart_update_timeout(struct uart_port *port, unsigned int cflag,
- unsigned int baud)
-{
- unsigned int bits;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5:
- bits = 7;
- break;
- case CS6:
- bits = 8;
- break;
- case CS7:
- bits = 9;
- break;
- default:
- bits = 10;
- break; /* CS8 */
- }
-
- if (cflag & CSTOPB)
- bits++;
- if (cflag & PARENB)
- bits++;
-
- /*
- * The total number of bits to be transmitted in the fifo.
- */
- bits = bits * port->fifosize;
-
- /*
- * Figure the timeout to send the above number of bits.
- * Add .02 seconds of slop
- */
- port->timeout = (HZ * bits) / baud + HZ/50;
-}
-
-EXPORT_SYMBOL(uart_update_timeout);
-
-/**
- * uart_get_baud_rate - return baud rate for a particular port
- * @port: uart_port structure describing the port in question.
- * @termios: desired termios settings.
- * @old: old termios (or NULL)
- * @min: minimum acceptable baud rate
- * @max: maximum acceptable baud rate
- *
- * Decode the termios structure into a numeric baud rate,
- * taking account of the magic 38400 baud rate (with spd_*
- * flags), and mapping the %B0 rate to 9600 baud.
- *
- * If the new baud rate is invalid, try the old termios setting.
- * If it's still invalid, we try 9600 baud.
- *
- * Update the @termios structure to reflect the baud rate
- * we're actually going to be using. Don't do this for the case
- * where B0 is requested ("hang up").
- */
-unsigned int
-uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old, unsigned int min, unsigned int max)
-{
- unsigned int try;
- unsigned int baud;
- unsigned int altbaud;
- int hung_up = 0;
- upf_t flags = port->flags & UPF_SPD_MASK;
-
- switch (flags) {
- case UPF_SPD_HI:
- altbaud = 57600;
- break;
- case UPF_SPD_VHI:
- altbaud = 115200;
- break;
- case UPF_SPD_SHI:
- altbaud = 230400;
- break;
- case UPF_SPD_WARP:
- altbaud = 460800;
- break;
- default:
- altbaud = 38400;
- break;
- }
-
- for (try = 0; try < 2; try++) {
- baud = tty_termios_baud_rate(termios);
-
- /*
- * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
- * Die! Die! Die!
- */
- if (try == 0 && baud == 38400)
- baud = altbaud;
-
- /*
- * Special case: B0 rate.
- */
- if (baud == 0) {
- hung_up = 1;
- baud = 9600;
- }
-
- if (baud >= min && baud <= max)
- return baud;
-
- /*
- * Oops, the quotient was zero. Try again with
- * the old baud rate if possible.
- */
- termios->c_cflag &= ~CBAUD;
- if (old) {
- baud = tty_termios_baud_rate(old);
- if (!hung_up)
- tty_termios_encode_baud_rate(termios,
- baud, baud);
- old = NULL;
- continue;
- }
-
- /*
- * As a last resort, if the range cannot be met then clip to
- * the nearest chip supported rate.
- */
- if (!hung_up) {
- if (baud <= min)
- tty_termios_encode_baud_rate(termios,
- min + 1, min + 1);
- else
- tty_termios_encode_baud_rate(termios,
- max - 1, max - 1);
- }
- }
- /* Should never happen */
- WARN_ON(1);
- return 0;
-}
-
-EXPORT_SYMBOL(uart_get_baud_rate);
-
-/**
- * uart_get_divisor - return uart clock divisor
- * @port: uart_port structure describing the port.
- * @baud: desired baud rate
- *
- * Calculate the uart clock divisor for the port.
- */
-unsigned int
-uart_get_divisor(struct uart_port *port, unsigned int baud)
-{
- unsigned int quot;
-
- /*
- * Old custom speed handling.
- */
- if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
- quot = port->custom_divisor;
- else
- quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
-
- return quot;
-}
-
-EXPORT_SYMBOL(uart_get_divisor);
-
/* Caller holds port mutex */
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios)
@@ -1843,207 +1660,6 @@ static const struct file_operations uart_proc_fops = {
};
#endif
-#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
-/**
- * uart_console_write - write a console message to a serial port
- * @port: the port to write the message
- * @s: array of characters
- * @count: number of characters in string to write
- * @putchar: function to write character to port
- */
-void uart_console_write(struct uart_port *port, const char *s,
- unsigned int count,
- void (*putchar)(struct uart_port *, int))
-{
- unsigned int i;
-
- for (i = 0; i < count; i++, s++) {
- if (*s == '\n')
- putchar(port, '\r');
- putchar(port, *s);
- }
-}
-EXPORT_SYMBOL_GPL(uart_console_write);
-
-/*
- * Check whether an invalid uart number has been specified, and
- * if so, search for the first available port that does have
- * console support.
- */
-struct uart_port * __init
-uart_get_console(struct uart_port *ports, int nr, struct console *co)
-{
- int idx = co->index;
-
- if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 &&
- ports[idx].membase == NULL))
- for (idx = 0; idx < nr; idx++)
- if (ports[idx].iobase != 0 ||
- ports[idx].membase != NULL)
- break;
-
- co->index = idx;
-
- return ports + idx;
-}
-
-/**
- * uart_parse_earlycon - Parse earlycon options
- * @p: ptr to 2nd field (ie., just beyond '<name>,')
- * @iotype: ptr for decoded iotype (out)
- * @addr: ptr for decoded mapbase/iobase (out)
- * @options: ptr for <options> field; NULL if not present (out)
- *
- * Decodes earlycon kernel command line parameters of the form
- * earlycon=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
- * console=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
- *
- * The optional form
- * earlycon=<name>,0x<addr>,<options>
- * console=<name>,0x<addr>,<options>
- * is also accepted; the returned @iotype will be UPIO_MEM.
- *
- * Returns 0 on success or -EINVAL on failure
- */
-int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr,
- char **options)
-{
- if (strncmp(p, "mmio,", 5) == 0) {
- *iotype = UPIO_MEM;
- p += 5;
- } else if (strncmp(p, "mmio16,", 7) == 0) {
- *iotype = UPIO_MEM16;
- p += 7;
- } else if (strncmp(p, "mmio32,", 7) == 0) {
- *iotype = UPIO_MEM32;
- p += 7;
- } else if (strncmp(p, "mmio32be,", 9) == 0) {
- *iotype = UPIO_MEM32BE;
- p += 9;
- } else if (strncmp(p, "mmio32native,", 13) == 0) {
- *iotype = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
- UPIO_MEM32BE : UPIO_MEM32;
- p += 13;
- } else if (strncmp(p, "io,", 3) == 0) {
- *iotype = UPIO_PORT;
- p += 3;
- } else if (strncmp(p, "0x", 2) == 0) {
- *iotype = UPIO_MEM;
- } else {
- return -EINVAL;
- }
-
- /*
- * Before you replace it with kstrtoull(), think about options separator
- * (',') it will not tolerate
- */
- *addr = simple_strtoull(p, NULL, 0);
- p = strchr(p, ',');
- if (p)
- p++;
-
- *options = p;
- return 0;
-}
-EXPORT_SYMBOL_GPL(uart_parse_earlycon);
-
-/**
- * uart_parse_options - Parse serial port baud/parity/bits/flow control.
- * @options: pointer to option string
- * @baud: pointer to an 'int' variable for the baud rate.
- * @parity: pointer to an 'int' variable for the parity.
- * @bits: pointer to an 'int' variable for the number of data bits.
- * @flow: pointer to an 'int' variable for the flow control character.
- *
- * uart_parse_options decodes a string containing the serial console
- * options. The format of the string is <baud><parity><bits><flow>,
- * eg: 115200n8r
- */
-void
-uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
-{
- char *s = options;
-
- *baud = simple_strtoul(s, NULL, 10);
- while (*s >= '0' && *s <= '9')
- s++;
- if (*s)
- *parity = *s++;
- if (*s)
- *bits = *s++ - '0';
- if (*s)
- *flow = *s;
-}
-EXPORT_SYMBOL_GPL(uart_parse_options);
-
-/**
- * uart_set_options - setup the serial console parameters
- * @port: pointer to the serial ports uart_port structure
- * @co: console pointer
- * @baud: baud rate
- * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
- * @bits: number of data bits
- * @flow: flow control character - 'r' (rts)
- */
-int
-uart_set_options(struct uart_port *port, struct console *co,
- int baud, int parity, int bits, int flow)
-{
- struct ktermios termios;
- static struct ktermios dummy;
-
- /*
- * Ensure that the serial console lock is initialised
- * early.
- * If this port is a console, then the spinlock is already
- * initialised.
- */
- if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) {
- spin_lock_init(&port->lock);
- lockdep_set_class(&port->lock, &port_lock_key);
- }
-
- memset(&termios, 0, sizeof(struct ktermios));
-
- termios.c_cflag |= CREAD | HUPCL | CLOCAL;
- tty_termios_encode_baud_rate(&termios, baud, baud);
-
- if (bits == 7)
- termios.c_cflag |= CS7;
- else
- termios.c_cflag |= CS8;
-
- switch (parity) {
- case 'o': case 'O':
- termios.c_cflag |= PARODD;
- /*fall through*/
- case 'e': case 'E':
- termios.c_cflag |= PARENB;
- break;
- }
-
- if (flow == 'r')
- termios.c_cflag |= CRTSCTS;
-
- /*
- * some uarts on other side don't support no flow control.
- * So we set * DTR in host uart to make them happy
- */
- port->mctrl |= TIOCM_DTR;
-
- port->ops->set_termios(port, &termios, &dummy);
- /*
- * Allow the setting of the UART parameters with a NULL console
- * too:
- */
- if (co)
- co->cflag = termios.c_cflag;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(uart_set_options);
-#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-
/**
* uart_change_pm - set power state of the port
*
@@ -2756,15 +2372,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
state->pm_state = UART_PM_STATE_UNDEFINED;
uport->cons = drv->cons;
uport->minor = drv->tty_driver->minor_start + uport->line;
+ uart_port_lock_init(uport);
- /*
- * If this port is a console, then the spinlock is already
- * initialised.
- */
- if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
- spin_lock_init(&uport->lock);
- lockdep_set_class(&uport->lock, &port_lock_key);
- }
if (uport->cons && uport->dev)
of_console_check(uport->dev->of_node, uport->cons->name, uport->line);
@@ -2890,32 +2499,6 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
return ret;
}
-/*
- * Are the two ports equivalent?
- */
-int uart_match_port(struct uart_port *port1, struct uart_port *port2)
-{
- if (port1->iotype != port2->iotype)
- return 0;
-
- switch (port1->iotype) {
- case UPIO_PORT:
- return (port1->iobase == port2->iobase);
- case UPIO_HUB6:
- return (port1->iobase == port2->iobase) &&
- (port1->hub6 == port2->hub6);
- case UPIO_MEM:
- case UPIO_MEM16:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_AU:
- case UPIO_TSI:
- return (port1->mapbase == port2->mapbase);
- }
- return 0;
-}
-EXPORT_SYMBOL(uart_match_port);
-
/**
* uart_handle_dcd_change - handle a change of carrier detect state
* @uport: uart_port structure for the open port
diff --git a/drivers/tty/serial/minitty_serial.c b/drivers/tty/serial/minitty_serial.c
new file mode 100644
index 00000000..d5bcc35e
--- /dev/null
+++ b/drivers/tty/serial/minitty_serial.c
@@ -0,0 +1,1793 @@
+/*
+* Smallest shortcut replacement for tty and serial core layers.
+*
+* Based mainly on tty_io.c, n_tty.c and serial_core.c from many smart people.
+*
+* Created by: Nicolas Pitre, January 2017
+* Copyright: (C) 2017 Linaro Limited
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/ctype.h>
+#include <linux/console.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/serial_core.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+struct minitty_data {
+ struct uart_state state;
+ struct ktermios termios;
+ struct mutex mutex;
+ unsigned char *rx_buf;
+ int rx_head, rx_vetted, rx_tail;
+ int rx_lines, column, canon_start_pos;
+ bool rx_raw;
+ bool rx_overflow;
+ wait_queue_head_t write_wait;
+ wait_queue_head_t read_wait;
+ struct work_struct rx_work;
+ struct cdev cdev;
+ struct device *dev;
+ int usecount;
+};
+
+#define RX_BUF_SIZE PAGE_SIZE
+#define RX_BUF_WRAP(x) ((x) & (RX_BUF_SIZE - 1))
+
+/*
+* Functions called back by low level UART drivers when
+* the TX buffer is getting near empty.
+*/
+void uart_write_wakeup(struct uart_port *port)
+{
+ struct uart_state *state = port->state;
+ struct minitty_data *mtty = container_of(state, typeof(*mtty), state);
+
+ wake_up_interruptible_poll(&mtty->write_wait, POLLOUT);
+}
+EXPORT_SYMBOL(uart_write_wakeup);
+
+static void
+uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
+{
+ unsigned long flags;
+ unsigned int old;
+
+ spin_lock_irqsave(&port->lock, flags);
+ old = port->mctrl;
+ port->mctrl = (old & ~clear) | set;
+ if (old != port->mctrl)
+ port->ops->set_mctrl(port, port->mctrl);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+#define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0)
+#define uart_clear_mctrl(port, clear) uart_update_mctrl(port, 0, clear)
+
+static void uart_change_pm(struct uart_state *state,
+ enum uart_pm_state pm_state)
+{
+ struct uart_port *port =state->uart_port;
+
+ if (state->pm_state != pm_state) {
+ if (port && port->ops->pm)
+ port->ops->pm(port, pm_state, state->pm_state);
+ state->pm_state = pm_state;
+ }
+}
+
+int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
+{
+ return -EPROTONOSUPPORT;
+}
+EXPORT_SYMBOL(uart_suspend_port);
+
+int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
+{
+ return -EPROTONOSUPPORT;
+}
+EXPORT_SYMBOL(uart_resume_port);
+
+/**
+* uart_handle_dcd_change - handle a change of carrier detect state
+* @port: uart_port structure for the open port
+* @status: new carrier detect status, nonzero if active
+*
+* Caller must hold port->lock
+*/
+void uart_handle_dcd_change(struct uart_port *port, unsigned int status)
+{
+ port->icount.dcd++;
+}
+EXPORT_SYMBOL_GPL(uart_handle_dcd_change);
+
+/**
+* uart_handle_cts_change - handle a change of clear-to-send state
+* @port: uart_port structure for the open port
+* @status: new clear to send status, nonzero if active
+*
+* Caller must hold port->lock
+*/
+void uart_handle_cts_change(struct uart_port *port, unsigned int status)
+{
+ port->icount.cts++;
+
+ if (uart_softcts_mode(port)) {
+ if (port->hw_stopped) {
+ if (status) {
+ port->hw_stopped = 0;
+ port->ops->start_tx(port);
+ uart_write_wakeup(port);
+ }
+ } else {
+ if (!status) {
+ port->hw_stopped = 1;
+ port->ops->stop_tx(port);
+ }
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(uart_handle_cts_change);
+
+static void uart_start_tx(struct minitty_data *mtty)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ spin_lock_irq(&port->lock);
+ if (!port->hw_stopped)
+ port->ops->start_tx(port);
+ spin_unlock_irq(&port->lock);
+}
+
+static int uart_chars_in_buffer(struct minitty_data *mtty)
+{
+ struct uart_state *state = &mtty->state;
+ struct uart_port *port = mtty->state.uart_port;
+ int ret;
+
+ spin_lock_irq(&port->lock);
+ ret = uart_circ_chars_pending(&state->xmit);
+ spin_unlock_irq(&port->lock);
+ return ret;
+}
+
+static void uart_flush_tx_buffer(struct minitty_data *mtty)
+{
+ struct uart_state *state = &mtty->state;
+ struct uart_port *port = mtty->state.uart_port;
+
+ spin_lock_irq(&port->lock);
+ uart_circ_clear(&state->xmit);
+ if (port->ops->flush_buffer)
+ port->ops->flush_buffer(port);
+ spin_unlock_irq(&port->lock);
+ uart_write_wakeup(port);
+}
+
+static int uart_get_lsr_info(struct minitty_data *mtty, unsigned int __user *p)
+{
+ struct uart_state *state = &mtty->state;
+ struct uart_port *port = mtty->state.uart_port;
+ unsigned int result;
+
+ mutex_lock(&mtty->mutex);
+ result = port->ops->tx_empty(port);
+
+ /*
+ * If we're about to load something into the transmit
+ * register, we'll pretend the transmitter isn't empty to
+ * avoid a race condition (depending on when the transmit
+ * interrupt happens).
+ */
+ if (port->x_char ||
+ ((uart_circ_chars_pending(&state->xmit) > 0) &&
+ !uart_tx_stopped(port)))
+ result &= ~TIOCSER_TEMT;
+ mutex_unlock(&mtty->mutex);
+ return put_user(result, p);
+}
+
+static int uart_tiocmget(struct minitty_data *mtty, int __user *p)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ int ret = -EIO;
+
+ mutex_lock(&mtty->mutex);
+ ret = port->mctrl;
+ spin_lock_irq(&port->lock);
+ ret |= port->ops->get_mctrl(port);
+ spin_unlock_irq(&port->lock);
+ mutex_unlock(&mtty->mutex);
+ if (ret >= 0)
+ ret = put_user(ret, p);
+ return ret;
+}
+
+static int
+uart_tiocmset(struct minitty_data *mtty, unsigned int cmd, unsigned __user *p)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ unsigned int set, clear, val;
+ int ret;
+
+ ret = get_user(val, p);
+ if (ret)
+ return ret;
+ set = clear = 0;
+ switch (cmd) {
+ case TIOCMBIS:
+ set = val;
+ break;
+ case TIOCMBIC:
+ clear = val;
+ break;
+ case TIOCMSET:
+ set = val;
+ clear = ~val;
+ break;
+ }
+ set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
+ clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
+
+ mutex_lock(&mtty->mutex);
+ uart_update_mctrl(port, set, clear);
+ mutex_unlock(&mtty->mutex);
+ return 0;
+}
+
+static int uart_break_ctl(struct minitty_data *mtty, int break_state)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ int ret = -EIO;
+
+ mutex_lock(&mtty->mutex);
+ port->ops->break_ctl(port, break_state);
+ mutex_unlock(&mtty->mutex);
+ return ret;
+}
+
+/*
+* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+* - mask passed in arg for lines of interest
+* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+* Caller should use TIOCGICOUNT to see which one it was
+*/
+static int uart_wait_modem_status(struct minitty_data *mtty, unsigned long arg)
+{
+ struct uart_port *uport = mtty->state.uart_port;
+ struct tty_port *port = &mtty->state.port;
+ DECLARE_WAITQUEUE(wait, current);
+ struct uart_icount cprev, cnow;
+ int ret;
+
+ /*
+ * note the counters on entry
+ */
+ spin_lock_irq(&uport->lock);
+ memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
+ if (uport->ops->enable_ms)
+ uport->ops->enable_ms(uport);
+ spin_unlock_irq(&uport->lock);
+
+ add_wait_queue(&port->delta_msr_wait, &wait);
+ for (;;) {
+ spin_lock_irq(&uport->lock);
+ memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
+ spin_unlock_irq(&uport->lock);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+ ret = 0;
+ break;
+ }
+
+ schedule();
+
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ cprev = cnow;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&port->delta_msr_wait, &wait);
+
+ return ret;
+}
+
+/*
+* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+* NB: both 1->0 and 0->1 transitions are counted except for
+* RI where only 0->1 is counted.
+*/
+static int uart_tiocgicount(struct minitty_data *mtty, void __user *p)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ struct serial_icounter_struct icount;
+ struct uart_icount cnow;
+
+ spin_lock_irq(&port->lock);
+ memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
+ spin_unlock_irq(&port->lock);
+
+ memset(&icount, 0, sizeof(icount));
+ icount.cts = cnow.cts;
+ icount.dsr = cnow.dsr;
+ icount.rng = cnow.rng;
+ icount.dcd = cnow.dcd;
+ icount.rx = cnow.rx;
+ icount.tx = cnow.tx;
+ icount.frame = cnow.frame;
+ icount.overrun = cnow.overrun;
+ icount.parity = cnow.parity;
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+ if (copy_to_user(p, &icount, sizeof(icount)))
+ return -EFAULT;
+ return 0;
+}
+
+static void uart_change_speed(struct minitty_data *mtty,
+ struct ktermios *old_termios)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ struct ktermios *termios = &mtty->termios;
+ int hw_stopped;
+
+ port->ops->set_termios(port, termios, old_termios);
+
+ /*
+ * Set modem status enables based on termios cflag
+ */
+ spin_lock_irq(&port->lock);
+ if (termios->c_cflag & CRTSCTS)
+ port->status |= UPSTAT_CTS_ENABLE;
+ else
+ port->status &= ~UPSTAT_CTS_ENABLE;
+
+ if (termios->c_cflag & CLOCAL)
+ port->status &= ~UPSTAT_DCD_ENABLE;
+ else
+ port->status |= UPSTAT_DCD_ENABLE;
+
+ /* reset sw-assisted CTS flow control based on (possibly) new mode */
+ hw_stopped = port->hw_stopped;
+ port->hw_stopped = uart_softcts_mode(port) &&
+ !(port->ops->get_mctrl(port) & TIOCM_CTS);
+ if (port->hw_stopped) {
+ if (!hw_stopped)
+ port->ops->stop_tx(port);
+ } else {
+ if (hw_stopped)
+ port->ops->start_tx(port);
+ }
+ spin_unlock_irq(&port->lock);
+}
+
+static void uart_set_termios(struct minitty_data *mtty,
+ struct ktermios *old_termios)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ unsigned int cflag = mtty->termios.c_cflag;
+ unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK;
+ bool sw_changed = false;
+
+ /*
+ * Drivers doing software flow control also need to know
+ * about changes to these input settings.
+ */
+ if (port->flags & UPF_SOFT_FLOW) {
+ iflag_mask |= IXANY|IXON|IXOFF;
+ sw_changed =
+ mtty->termios.c_cc[VSTART] != old_termios->c_cc[VSTART] ||
+ mtty->termios.c_cc[VSTOP] != old_termios->c_cc[VSTOP];
+ }
+
+ /*
+ * These are the bits that are used to setup various
+ * flags in the low level driver. We can ignore the Bfoo
+ * bits in c_cflag; c_[io]speed will always be set
+ * appropriately by set_termios().
+ */
+ if ((cflag ^ old_termios->c_cflag) == 0 &&
+ mtty->termios.c_ospeed == old_termios->c_ospeed &&
+ mtty->termios.c_ispeed == old_termios->c_ispeed &&
+ ((mtty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 &&
+ !sw_changed)
+ return;
+
+ uart_change_speed(mtty, old_termios);
+ /* reload cflag from termios; port driver may have overriden flags */
+ cflag = mtty->termios.c_cflag;
+
+ /* Handle transition to B0 status */
+ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
+ uart_clear_mctrl(port, TIOCM_RTS | TIOCM_DTR);
+ /* Handle transition away from B0 status */
+ else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
+ unsigned int mask = TIOCM_DTR;
+ if (!(cflag & CRTSCTS))
+ mask |= TIOCM_RTS;
+ uart_set_mctrl(port, mask);
+ }
+}
+
+static void uart_wait_until_sent(struct minitty_data *mtty)
+{
+ struct uart_port *port = mtty->state.uart_port;
+ unsigned long char_time, expire, timeout;
+
+ /*
+ * Set the check interval to be 1/5 of the estimated time to
+ * send a single character, and make it at least 1.
+ *
+ * Note: we have to use pretty tight timings here to satisfy
+ * the NIST-PCTS.
+ */
+ char_time = (port->timeout - HZ/50) / port->fifosize;
+ char_time = char_time / 5;
+ if (char_time == 0)
+ char_time = 1;
+
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than port->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*port->timeout.
+ */
+ timeout = 2 * port->timeout;
+
+ expire = jiffies + timeout;
+ while (!port->ops->tx_empty(port)) {
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ if (signal_pending(current))
+ break;
+ if (time_after(jiffies, expire))
+ break;
+ }
+}
+
+static void mtty_wait_until_sent(struct minitty_data *mtty)
+{
+ long timeout = MAX_SCHEDULE_TIMEOUT;
+
+ timeout = wait_event_interruptible_timeout(mtty->write_wait,
+ !uart_chars_in_buffer(mtty), timeout);
+ if (timeout > 0)
+ uart_wait_until_sent(mtty);
+}
+
+static void mtty_set_termios(struct minitty_data *mtty,
+ struct ktermios *old_termios)
+{
+ bool was_raw = mtty->rx_raw;
+
+ mtty->rx_raw = !I_IGNCR(mtty) && !I_ICRNL(mtty) && !I_INLCR(mtty) &&
+ !L_ICANON(mtty) && !L_ISIG(mtty) && !L_ECHO(mtty);
+ if (!mtty->rx_raw && was_raw)
+ mtty->rx_lines = mtty->column = mtty->canon_start_pos = 0;
+
+ /* mark things we don't support. */
+ mtty->termios.c_iflag |= IGNBRK | IGNPAR;
+ mtty->termios.c_iflag &= ~(ISTRIP | IUCLC | IXON | IXOFF);
+ mtty->termios.c_lflag &= ~IEXTEN;
+
+ /* The termios change make the tty ready for I/O */
+ wake_up_interruptible(&mtty->write_wait);
+ wake_up_interruptible(&mtty->read_wait);
+}
+
+static int set_termios(struct minitty_data *mtty, unsigned int cmd,
+ void __user *arg)
+{
+ struct ktermios new_termios, old_termios;
+ int ret;
+
+ mutex_lock(&mtty->mutex);
+ new_termios = mtty->termios;
+ mutex_unlock(&mtty->mutex);
+
+ switch (cmd) {
+ case TCSETAF:
+ case TCSETAW:
+ case TCSETA:
+ ret = user_termio_to_kernel_termios(&new_termios,
+ (struct termio __user *)arg);
+ break;
+#ifdef TCGETS2
+ case TCSETSF2:
+ case TCSETSW2:
+ case TCSETS2:
+ ret = user_termios_to_kernel_termios(&new_termios,
+ (struct termios2 __user *)arg);
+ break;
+ default:
+ ret = user_termios_to_kernel_termios_1(&new_termios,
+ (struct termios __user *)arg);
+ break;
+#else
+ default:
+ ret = user_termios_to_kernel_termios(&new_termios,
+ (struct termios __user *)arg);
+ break;
+#endif
+ }
+ if (ret)
+ return -EFAULT;
+
+ switch (cmd) {
+ case TCSETSF:
+#ifdef TCGETS2
+ case TCSETSF2:
+#endif
+ case TCSETAF:
+ uart_flush_tx_buffer(mtty);
+ }
+
+ switch (cmd) {
+ case TCSETSF:
+ case TCSETSW:
+#ifdef TCGETS2
+ case TCSETSF2:
+ case TCSETSW2:
+#endif
+ case TCSETAF:
+ case TCSETAW:
+ mtty_wait_until_sent(mtty);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+
+ /*
+ * If old style Bfoo values are used then load c_ispeed/c_ospeed
+ * with the real speed so its unconditionally usable.
+ */
+ new_termios.c_ispeed = tty_termios_input_baud_rate(&new_termios);
+ new_termios.c_ospeed = tty_termios_baud_rate(&new_termios);
+
+ mutex_lock(&mtty->mutex);
+ old_termios = mtty->termios;
+ mtty->termios = new_termios;
+ mtty_set_termios(mtty, &old_termios);
+ uart_set_termios(mtty, &old_termios);
+ mutex_unlock(&mtty->mutex);
+ return 0;
+}
+
+static int tiocsetd(int __user *p)
+{
+ int ldisc;
+
+ if (get_user(ldisc, p))
+ return -EFAULT;
+ if (ldisc != N_TTY)
+ return -EINVAL;
+ return 0;
+}
+
+static int tiocgetd(int __user *p)
+{
+ return put_user(N_TTY, p);
+}
+
+static void copy_termios(struct minitty_data *mtty, struct ktermios *kterm)
+{
+ mutex_lock(&mtty->mutex);
+ *kterm = mtty->termios;
+ mutex_unlock(&mtty->mutex);
+}
+
+static long minitty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct minitty_data *mtty = file->private_data;
+ struct uart_port *port = mtty->state.uart_port;
+ void __user *p = (void __user *)arg;
+ struct ktermios kterm;
+ int ret = -ENOIOCTLCMD;
+
+ switch (cmd) {
+ case TIOCSETD:
+ return tiocsetd(p);
+ case TIOCGETD:
+ return tiocgetd(p);
+ case TIOCSBRK:
+ return uart_break_ctl(mtty, -1);
+ case TIOCCBRK:
+ return uart_break_ctl(mtty, 0);
+ case TIOCMGET:
+ return uart_tiocmget(mtty, p);
+ case TIOCMSET:
+ case TIOCMBIC:
+ case TIOCMBIS:
+ return uart_tiocmset(mtty, cmd, p);
+ case TIOCGICOUNT:
+ return uart_tiocgicount(mtty, p);
+ case TIOCMIWAIT:
+ return uart_wait_modem_status(mtty, arg);
+ case TIOCSERGETLSR:
+ return uart_get_lsr_info(mtty, p);
+
+#ifndef TCGETS2
+ case TCGETS:
+ copy_termios(mtty, &kterm);
+ if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
+ return -EFAULT;
+ return 0;
+#else
+ case TCGETS:
+ copy_termios(mtty, &kterm);
+ if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
+ return -EFAULT;
+ return 0;
+ case TCGETS2:
+ copy_termios(mtty, &kterm);
+ if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
+ return -EFAULT;
+ return 0;
+ case TCSETSF2:
+ case TCSETSW2:
+ case TCSETS2:
+#endif
+ case TCSETSF:
+ case TCSETSW:
+ case TCSETS:
+ case TCSETAF:
+ case TCSETAW:
+ case TCSETA:
+ return set_termios(mtty, cmd, p);
+ case TCGETA:
+ copy_termios(mtty, &kterm);
+ if (kernel_termios_to_user_termio((struct termio __user *)arg, &kterm))
+ return -EFAULT;
+ return 0;
+
+ default:
+ mutex_lock(&mtty->mutex);
+ if (port->ops->ioctl)
+ ret = port->ops->ioctl(port, cmd, arg);
+ mutex_unlock(&mtty->mutex);
+ break;
+ }
+
+ if (ret == -ENOIOCTLCMD)
+ ret = -EINVAL;
+ return ret;
+}
+
+/*
+* Functions called back by low level UART drivers normally provided by
+* the regular TTY layer to deliver RX data that we have to emulate.
+* We ssimply ignore characters with errors here.
+*/
+
+int tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
+{
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct minitty_data *mtty = container_of(state, typeof(*mtty), state);
+
+ if (flag == TTY_NORMAL) {
+ int tail = smp_load_acquire(&mtty->rx_tail);
+ int head = mtty->rx_head;
+ int next = RX_BUF_WRAP(head + 1);
+ /*
+ * Advance head only if buffer is not full.
+ * Keep on overwriting last char otherwise.
+ */
+ mtty->rx_buf[head] = ch;
+ if (next != tail) {
+ smp_store_release(&mtty->rx_head, next);
+ return 1;
+ } else {
+ smp_store_release(&mtty->rx_overflow, true);
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(tty_insert_flip_char);
+
+void uart_insert_char(struct uart_port *port, unsigned int status,
+ unsigned int overrun, unsigned int ch, unsigned int flag)
+{
+ struct uart_state *state = port->state;
+ struct minitty_data *mtty = container_of(state, typeof(*mtty), state);
+
+ if (flag == TTY_NORMAL) {
+ int tail = smp_load_acquire(&mtty->rx_tail);
+ int head = mtty->rx_head;
+ int next = RX_BUF_WRAP(head + 1);
+ /*
+ * Advance head only if buffer is not full.
+ * Keep on overwriting last char otherwise.
+ */
+ mtty->rx_buf[head] = ch;
+ if (next != tail) {
+ smp_store_release(&mtty->rx_head, next);
+ } else {
+ smp_store_release(&mtty->rx_overflow, true);
+ port->icount.buf_overrun++;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(uart_insert_char);
+
+int tty_insert_flip_string(struct tty_port *port, const unsigned char *chars,
+ size_t size)
+{
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct minitty_data *mtty = container_of(state, typeof(*mtty), state);
+ int head, tail, len, ret = 0;
+
+ tail = smp_load_acquire(&mtty->rx_tail);
+ head = mtty->rx_head;
+ do {
+ len = CIRC_SPACE(head, tail, RX_BUF_SIZE);
+ if (len > size)
+ len = size;
+ memcpy(mtty->rx_buf+head, chars, len);
+ head = RX_BUF_WRAP(head + len);
+ chars += len;
+ size -= len;
+ ret += len;
+ } while (size && len && head == 0);
+ smp_store_release(&mtty->rx_head, head);
+ return ret;
+}
+EXPORT_SYMBOL(tty_insert_flip_string);
+
+int tty_buffer_request_room(struct tty_port *port, size_t size)
+{
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct minitty_data *mtty = container_of(state, typeof(*mtty), state);
+ int tail = smp_load_acquire(&mtty->rx_tail);
+ int head = mtty->rx_head;
+ int space = CIRC_SPACE(head, tail, RX_BUF_SIZE);
+ return size < space ? size : space;
+}
+EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+
+void tty_schedule_flip(struct tty_port *port)
+{
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct minitty_data *mtty = container_of(state, typeof(*mtty), state);
+
+ queue_work(system_unbound_wq, &mtty->rx_work);
+}
+EXPORT_SYMBOL(tty_schedule_flip);
+
+void tty_flip_buffer_push(struct tty_port *port)
+{
+ tty_schedule_flip(port);
+}
+EXPORT_SYMBOL(tty_flip_buffer_push);
+
+/*
+* Line Discipline Stuff
+*/
+
+static bool is_utf8_continuation(struct minitty_data *mtty, unsigned char c)
+{
+ return (I_IUTF8(mtty) && (c & 0xc0) == 0x80);
+}
+
+static bool is_line_termination(struct minitty_data *mtty, unsigned char c)
+{
+ return (c == '\n' || c == EOF_CHAR(mtty) || c == EOL_CHAR(mtty));
+}
+
+/*
+* Queue the provided character string in its entirety or nothing.
+* Return true if queued, false otherwise.
+*/
+static bool queue_tx_chars(struct minitty_data *mtty, unsigned char *s, int len)
+{
+ struct circ_buf *circ = &mtty->state.xmit;
+ int head, tail, space;
+
+ tail = smp_load_acquire(&circ->tail);
+ head = circ->head;
+ space = CIRC_SPACE(head, tail, UART_XMIT_SIZE);
+ if (space < len)
+ return false;
+ while (len--) {
+ circ->buf[head] = *s++;
+ head = (head + 1) & (UART_XMIT_SIZE - 1);
+ }
+ smp_store_release(&circ->head, head);
+ return true;
+}
+
+/*
+* Queue characters in their cooked sequence.
+* Return true if queued, or false otherwise.
+*/
+static bool tx_cooked_char(struct minitty_data *mtty, unsigned char c)
+{
+ int spaces, next_col = mtty->column;
+
+ switch (c) {
+ case '\n':
+ if (O_ONLRET(mtty))
+ next_col = 0;
+ if (O_ONLCR(mtty)) {
+ if (!queue_tx_chars(mtty, "\r\n", 2))
+ return false;
+ mtty->column = mtty->canon_start_pos = 0;
+ return true;
+ }
+ break;
+ case '\r':
+ if (O_ONOCR(mtty) && mtty->column == 0)
+ return true;
+ if (O_OCRNL(mtty)) {
+ c = '\n';
+ if (O_ONLRET(mtty))
+ next_col = 0;
+ } else
+ next_col = 0;
+ break;
+ case '\t':
+ spaces = 8 - (mtty->column & 7);
+ if (O_TABDLY(mtty) == XTABS) {
+ if (!queue_tx_chars(mtty, " ", spaces))
+ return false;
+ mtty->column += spaces;
+ return true;
+ }
+ next_col += spaces;
+ break;
+ case '\b':
+ if (next_col > 0)
+ next_col--;
+ break;
+ default:
+ if (iscntrl(c))
+ break;
+ if (is_utf8_continuation(mtty, c))
+ break;
+ next_col++;
+ break;
+ }
+ if (!queue_tx_chars(mtty, &c, 1))
+ return false;
+ mtty->column = next_col;
+ if (next_col == 0)
+ mtty->canon_start_pos = 0;
+ return true;
+}
+
+/*
+* Queue echoed characters, converting CTRL sequences into "^X" if need be.
+* Return true if queued, or false otherwise.
+*/
+static bool echo_rx_char(struct minitty_data *mtty, unsigned char c)
+{
+ if (L_ECHOCTL(mtty) && iscntrl(c) && c != '\t' && c != '\n') {
+ unsigned char buf[2];
+ buf[0] = '^';
+ buf[1] = c ^ 0100;
+ return queue_tx_chars(mtty, buf, 2);
+ }
+ if (O_OPOST(mtty))
+ return tx_cooked_char(mtty, c);
+ else
+ return queue_tx_chars(mtty, &c, 1);
+}
+
+/*
+* Remove character from RX buffer at given position by shifting
+* all preceding characters ahead.
+*/
+static void eat_rx_char(struct minitty_data *mtty, int pos)
+{
+ unsigned char *buf = mtty->rx_buf;
+ int tail = mtty->rx_tail;
+ int bottom = (tail <= pos) ? tail : 0;
+
+ memmove(&buf[bottom+1], &buf[bottom], pos - bottom);
+ if (tail > pos) {
+ buf[0] = buf[RX_BUF_SIZE-1];
+ memmove(&buf[tail+1], &buf[tail], RX_BUF_SIZE - 1 - tail);
+ }
+ smp_store_release(&mtty->rx_tail, RX_BUF_WRAP(tail + 1));
+}
+
+/*
+* Create needed erase sequence according to the erase character c at
+* position pos in the RX buffer. The erase sequence is sent for each
+* erased characters and only if that succeeds then the character is
+* actually removed from the buffer. The erase character itself is removed
+* last so if the whole erase sequence cannot be completed then this can
+* be resumed later.
+*/
+static bool erase_rx_char(struct minitty_data *mtty, unsigned char c, int pos)
+{
+ int prev_pos = RX_BUF_WRAP(pos - 1);
+ bool seen_alnum = false;
+
+ while (pos != mtty->rx_tail) {
+ unsigned char prev_c = mtty->rx_buf[prev_pos];
+
+ if (is_line_termination(mtty, prev_c)) {
+ /* End of previous line: we don't erase further. */
+ break;
+ }
+
+ if (is_utf8_continuation(mtty, prev_c)) {
+ /* UTF8 continuation char: we just drop it */
+ eat_rx_char(mtty, prev_pos);
+ continue;
+ }
+
+ if (c == WERASE_CHAR(mtty) && seen_alnum && !isalnum(prev_c)) {
+ /* Beginning of previous word: we don't erase further */
+ break;
+ }
+
+ if (prev_c == '\t') {
+ /* depends on characters before the tab */
+ int spaces = 0;
+ int i = prev_pos;
+ while (i != mtty->rx_tail) {
+ unsigned char before;
+ i = RX_BUF_WRAP(i - 1);
+ before = mtty->rx_buf[i];
+ if (before == '\t')
+ break;
+ if (is_line_termination(mtty, before))
+ break;
+ if (L_ECHOCTL(mtty) && iscntrl(before))
+ spaces += 2;
+ else if (is_utf8_continuation(mtty, before))
+ continue;
+ else if (!iscntrl(before))
+ spaces++;
+ }
+ if (i == mtty->rx_tail)
+ spaces += mtty->canon_start_pos;
+ spaces = 8 - (spaces & 7);
+ if (!queue_tx_chars(mtty, "\b\b\b\b\b\b\b\b", spaces))
+ return false;
+ mtty->column -= spaces;
+ } else if (L_ECHOCTL(mtty) && iscntrl(prev_c)) {
+ /* control chars were printed as "^X" */
+ if (!queue_tx_chars(mtty, "\b\b \b\b", 6))
+ return false;
+ mtty->column -= 2;
+ } else if (!iscntrl(prev_c)) {
+ if (!queue_tx_chars(mtty, "\b \b", 3))
+ return false;
+ mtty->column -= 1;
+ }
+
+ /* erase sequence sent, now remove the char from the buffer */
+ eat_rx_char(mtty, prev_pos);
+
+ if (c == ERASE_CHAR(mtty))
+ break;
+ }
+
+ /* Finally remove the erase character itself. */
+ eat_rx_char(mtty, pos);
+ return true;
+}
+
+/*
+* Process RX bytes: canonical mode, echo, signals, etc.
+* This might not process all RX characters if e.g. there is not enough
+* room in the TX buffer to contain corresponding echo sequences.
+*/
+static void minitty_process_rx(struct minitty_data *mtty)
+{
+ bool xmit = false;
+ int i, head;
+
+ head = smp_load_acquire(&mtty->rx_head);
+
+ if (mtty->rx_raw) {
+ smp_store_release(&mtty->rx_vetted, head);
+ return;
+ }
+
+ /*
+ * RX overflow mitigation: evaluate the last received character
+ * stored at the very head of the buffer in case it might be a
+ * signal or newline character that could kick the reader into
+ * action. We potentially overwrite the last vetted character but
+ * we're past any concern for lost characters at this point.
+ */
+ if (unlikely(mtty->rx_overflow)) {
+ WRITE_ONCE(mtty->rx_overflow, false);
+ if (RX_BUF_WRAP(head + 1) == mtty->rx_tail) {
+ i = RX_BUF_WRAP(head - 1);
+ mtty->rx_buf[i] = mtty->rx_buf[head];
+ if (mtty->rx_vetted == head)
+ mtty->rx_vetted = i;
+ }
+ }
+
+ for (i = mtty->rx_vetted; i != head; i = RX_BUF_WRAP(i + 1)) {
+ unsigned char c = mtty->rx_buf[i];
+
+ if (c == '\r') {
+ if (I_IGNCR(mtty)) {
+ eat_rx_char(mtty, i);
+ continue;
+ }
+ if (I_ICRNL(mtty))
+ mtty->rx_buf[i] = c = '\n';
+ } else if (c == '\n' && I_INLCR(mtty))
+ mtty->rx_buf[i] = c = '\r';
+
+ if (L_ICANON(mtty)) {
+ if ((L_ECHOE(mtty) && c == ERASE_CHAR(mtty)) ||
+ (L_ECHOE(mtty) && c == WERASE_CHAR(mtty)) ||
+ (L_ECHOK(mtty) && c == KILL_CHAR(mtty))) {
+ xmit = true;
+ if (!erase_rx_char(mtty, c, i))
+ break;
+ continue;
+ }
+ if (is_line_termination(mtty, c)) {
+ mtty->rx_lines++;
+ if (c != '\n')
+ continue;
+ }
+ }
+
+ if (L_ECHO(mtty) || (c == '\n' && L_ECHONL(mtty))) {
+ xmit = true;
+ if (!echo_rx_char(mtty, c))
+ break;
+ }
+ }
+
+ smp_store_release(&mtty->rx_vetted, i);
+
+ if (xmit)
+ uart_start_tx(mtty);
+}
+
+static bool rx_data_available(struct minitty_data *mtty, bool poll)
+{
+ bool data_avail = (mtty->rx_tail != mtty->rx_vetted);
+ if (data_avail && !L_ICANON(mtty)) {
+ int amt = poll && !TIME_CHAR(mtty) && MIN_CHAR(mtty) ?
+ MIN_CHAR(mtty) : 1;
+ data_avail = RX_BUF_WRAP(mtty->rx_vetted - mtty->rx_tail) >= amt;
+ } else if (data_avail && !mtty->rx_lines) {
+ /* wait for a full line */
+ data_avail = false;
+ } else if (!data_avail && mtty->rx_lines) {
+ /*
+ * This may happen if the RX buffer was flushed by a signal
+ * or during RX overflow. Let's just reset it to zero.
+ */
+ mtty->rx_lines = 0;
+ }
+ return data_avail;
+}
+
+static void uart_rx_work(struct work_struct *work)
+{
+ struct minitty_data *mtty = container_of(work, typeof(*mtty), rx_work);
+
+ mutex_lock(&mtty->mutex);
+ minitty_process_rx(mtty);
+ if (rx_data_available(mtty, true))
+ wake_up_interruptible_poll(&mtty->read_wait, POLLIN);
+ mutex_unlock(&mtty->mutex);
+}
+
+static ssize_t minitty_raw_read(struct minitty_data *mtty, char __user *buf,
+ size_t count)
+{
+ int head, tail, len, ret = 0;
+
+ head = smp_load_acquire(&mtty->rx_vetted);
+ tail = mtty->rx_tail;
+ do {
+ len = CIRC_CNT(head, tail, RX_BUF_SIZE);
+ if (len > count)
+ len = count;
+ if (copy_to_user(buf, mtty->rx_buf+tail, len) != 0)
+ return -EFAULT;
+ tail = RX_BUF_WRAP(tail + len);
+ buf += len;
+ count -= len;
+ ret += len;
+ } while (count && len && tail == 0);
+ smp_store_release(&mtty->rx_tail, tail);
+ return ret;
+}
+
+static ssize_t minitty_cooked_read(struct minitty_data *mtty, char __user *buf,
+ size_t count)
+{
+ int head, tail, i, ret;
+ bool eol = false;
+
+ head = smp_load_acquire(&mtty->rx_vetted);
+ tail = mtty->rx_tail;
+
+ /* First, locate the end-of-line marker if any. */
+ for (i = tail; i != head && count; i = RX_BUF_WRAP(i + 1), count--) {
+ unsigned char c = mtty->rx_buf[i];
+ if (is_line_termination(mtty, c)) {
+ eol = true;
+ break;
+ }
+ }
+
+ count = CIRC_CNT(i, tail, RX_BUF_SIZE);
+
+ if (eol) {
+ /* Include the line delimiter except for EOF */
+ if (mtty->rx_buf[i] != EOF_CHAR(mtty))
+ count++;
+ i = RX_BUF_WRAP(i + 1);
+ }
+
+ ret = minitty_raw_read(mtty, buf, count);
+ if (ret >= 0 && eol) {
+ /* we consumed a whole line */
+ mtty->rx_lines--;
+ /* adjust tail in case EOF was skipped */
+ smp_store_release(&mtty->rx_tail, i);
+ }
+ return ret;
+}
+
+static ssize_t minitty_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct minitty_data *mtty = file->private_data;
+ char __user *buf0 = buf;
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
+ int minimum, time;
+ long timeout;
+ int ret = 0;
+
+ mutex_lock(&mtty->mutex);
+
+ minimum = time = 0;
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ if (!L_ICANON(mtty)) {
+ minimum = MIN_CHAR(mtty);
+ if (minimum) {
+ time = (HZ / 10) * TIME_CHAR(mtty);
+ } else {
+ timeout = (HZ / 10) * TIME_CHAR(mtty);
+ minimum = 1;
+ }
+ }
+
+ add_wait_queue(&mtty->read_wait, &wait);
+
+ while (count) {
+ minitty_process_rx(mtty);
+
+ if (!rx_data_available(mtty, false)) {
+ if (!timeout)
+ break;
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ mutex_unlock(&mtty->mutex);
+ timeout = wait_woken(&wait, TASK_INTERRUPTIBLE,
+ timeout);
+ mutex_lock(&mtty->mutex);
+ continue;
+ }
+
+ if (L_ICANON(mtty)) {
+ ret = minitty_cooked_read(mtty, buf, count);
+ if (ret > 0)
+ buf += ret;
+ break;
+ }
+
+ ret = minitty_raw_read(mtty, buf, count);
+ if (ret < 0)
+ break;
+ buf += ret;
+ count -= ret;
+ if (buf - buf0 >= minimum)
+ break;
+ if (time)
+ timeout = time;
+ }
+
+ remove_wait_queue(&mtty->read_wait, &wait);
+ mutex_unlock(&mtty->mutex);
+ if (buf - buf0)
+ ret = buf - buf0;
+ return ret;
+}
+
+static ssize_t minitty_raw_write(struct minitty_data *mtty, const char __user *buf,
+ size_t count)
+{
+ struct circ_buf *circ = &mtty->state.xmit;
+ int head, tail, len, ret = 0;
+
+ tail = smp_load_acquire(&circ->tail);
+ head = circ->head;
+ do {
+ len = CIRC_SPACE_TO_END(head, tail, UART_XMIT_SIZE);
+ if (len > count)
+ len = count;
+ if (copy_from_user(circ->buf + head, buf, len) != 0)
+ return -EFAULT;
+ head = (head + len) & (UART_XMIT_SIZE - 1);
+ buf += len;
+ count -= len;
+ ret += len;
+ } while (count && len && head == 0);
+ smp_store_release(&circ->head, head);
+
+ uart_start_tx(mtty);
+ return ret;
+}
+
+static ssize_t minitty_cooked_write(struct minitty_data *mtty, const char __user *buf,
+ size_t count)
+{
+ const char __user *buf0 = buf;
+
+ while (count--) {
+ unsigned char c;
+ if (get_user(c, buf) != 0)
+ return -EFAULT;
+ if (!tx_cooked_char(mtty, c))
+ break;
+ buf++;
+ }
+ mtty->canon_start_pos = mtty->column;
+
+ uart_start_tx(mtty);
+ return buf - buf0;
+}
+
+static ssize_t minitty_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct minitty_data *mtty = file->private_data;
+ const char __user *buf0 = buf;
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
+ int ret;
+
+ mutex_lock(&mtty->mutex);
+ add_wait_queue(&mtty->write_wait, &wait);
+
+ while (1) {
+ /* give priority to RX echo and signals */
+ minitty_process_rx(mtty);
+
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+
+ if (O_OPOST(mtty))
+ ret = minitty_cooked_write(mtty, buf, count);
+ else
+ ret = minitty_raw_write(mtty, buf, count);
+ if (ret < 0)
+ break;
+ buf += ret;
+ count -= ret;
+ if (!count)
+ break;
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ mutex_unlock(&mtty->mutex);
+ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+ mutex_lock(&mtty->mutex);
+ }
+
+ remove_wait_queue(&mtty->write_wait, &wait);
+ mutex_unlock(&mtty->mutex);
+ return (buf - buf0) ? buf - buf0 : ret;
+}
+
+static unsigned int minitty_poll(struct file *file, poll_table *wait)
+{
+ struct minitty_data *mtty = file->private_data;
+ struct uart_port *port = mtty->state.uart_port;
+ unsigned int mask = 0;
+
+ mutex_lock(&mtty->mutex);
+
+ poll_wait(file, &mtty->read_wait, wait);
+ poll_wait(file, &mtty->write_wait, wait);
+
+ if (rx_data_available(mtty, true)) {
+ mask |= POLLIN | POLLRDNORM;
+ } else {
+ minitty_process_rx(mtty);
+ if (rx_data_available(mtty, true))
+ mask |= POLLIN | POLLRDNORM;
+ }
+
+ if (!port->hw_stopped) {
+ struct circ_buf *circ = &mtty->state.xmit;
+ int tail = smp_load_acquire(&circ->tail);
+ int head = circ->head;
+ int count = CIRC_CNT(head, tail, UART_XMIT_SIZE);
+ if (count < WAKEUP_CHARS)
+ mask |= POLLOUT | POLLWRNORM;
+ }
+
+ mutex_unlock(&mtty->mutex);
+
+ return mask;
+}
+
+static int uart_port_startup(struct minitty_data *mtty)
+{
+ struct uart_state *state = &mtty->state;
+ struct uart_port *port = state->uart_port;
+ unsigned long page;
+ int ret;
+
+ /* Make sure the device is in D0 state. */
+ uart_change_pm(state, UART_PM_STATE_ON);
+
+ /* Initialise and allocate the transmit buffer. */
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ state->xmit.buf = (unsigned char *) page;
+ uart_circ_clear(&state->xmit);
+
+ /* Initialise and allocate the receive buffer. */
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ ret = -ENOMEM;
+ goto err_free_tx;
+ }
+ mtty->rx_buf = (unsigned char *) page;
+ mtty->rx_head = mtty->rx_tail = mtty->rx_vetted = mtty->rx_lines = 0;
+ mtty->rx_overflow = false;
+
+ ret = port->ops->startup(port);
+ if (ret)
+ goto err_free_rx;
+
+ if (uart_console(port) && port->cons->cflag) {
+ mtty->termios.c_cflag = port->cons->cflag;
+ port->cons->cflag = 0;
+ }
+
+ /* Initialise the hardware port settings. */
+ uart_change_speed(mtty, NULL);
+
+ /*
+ * Setup the RTS and DTR signals once the
+ * port is open and ready to respond.
+ */
+ uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
+
+ return 0;
+
+err_free_rx:
+ free_page((unsigned long)mtty->rx_buf);
+ mtty->rx_buf = NULL;
+err_free_tx:
+ free_page((unsigned long)state->xmit.buf);
+ state->xmit.buf = NULL;
+ return ret;
+}
+
+/*
+* This routine will shutdown a serial port; interrupts are disabled, and
+* DTR is dropped if the hangup on close termio flag is on.
+*/
+static void uart_port_shutdown(struct minitty_data *mtty)
+{
+ struct uart_state *state = &mtty->state;
+ struct uart_port *port = state->uart_port;
+
+ spin_lock_irq(&port->lock);
+ port->ops->stop_rx(port);
+ spin_unlock_irq(&port->lock);
+
+ if (uart_console(port))
+ port->cons->cflag = mtty->termios.c_cflag;
+
+ /* Turn off DTR and RTS early. */
+ if (C_HUPCL(mtty))
+ uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+
+ /* Free the IRQ and disable the port. */
+ port->ops->shutdown(port);
+ synchronize_irq(port->irq);
+
+ /* Free the transmit buffer page. */
+ free_page((unsigned long)state->xmit.buf);
+ state->xmit.buf = NULL;
+
+ /* Free the receive buffer page. */
+ free_page((unsigned long)mtty->rx_buf);
+ mtty->rx_buf = NULL;
+}
+
+static int minitty_open(struct inode *inode, struct file *file)
+{
+ struct minitty_data *mtty = NULL;
+ dev_t devt = inode->i_rdev;
+ int ret = 0;
+
+ if (devt == MKDEV(TTYAUX_MAJOR, 1)) {
+ struct console *co;
+ struct uart_driver *drv;
+ console_lock();
+ for_each_console(co) {
+ if (co->device != uart_console_device)
+ continue;
+ drv = co->data;
+ mtty = container_of(drv->state, typeof(*mtty), state);
+ mtty += co->index;
+ break;
+ }
+ console_unlock();
+ if (!mtty)
+ return -ENODEV;
+ } else {
+ mtty = container_of(inode->i_cdev, typeof(*mtty), cdev);
+ }
+
+ nonseekable_open(inode, file);
+
+ file->private_data = mtty;
+
+ mutex_lock(&mtty->mutex);
+ if (!mtty->usecount++) {
+ ret = uart_port_startup(mtty);
+ if (ret)
+ mtty->usecount--;
+ }
+ mutex_unlock(&mtty->mutex);
+ return ret;
+}
+
+static int minitty_release(struct inode *inode, struct file *file)
+{
+ struct minitty_data *mtty = file->private_data;
+ struct uart_state *state = &mtty->state;
+ struct uart_port *port = state->uart_port;
+
+ mutex_lock(&mtty->mutex);
+ mtty->usecount--;
+ if (!mtty->usecount) {
+ uart_flush_tx_buffer(mtty);
+ uart_port_shutdown(mtty);
+ if (!uart_console(port))
+ uart_change_pm(state, UART_PM_STATE_OFF);
+ }
+ mutex_unlock(&mtty->mutex);
+ return 0;
+}
+
+static const struct file_operations minitty_fops = {
+ .llseek = no_llseek,
+ .read = minitty_read,
+ .write = minitty_write,
+ .poll = minitty_poll,
+ .unlocked_ioctl = minitty_ioctl,
+ .open = minitty_open,
+ .release = minitty_release,
+};
+
+struct class *minitty_class;
+
+static int
+uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+ struct uart_port *port)
+{
+ unsigned int flags;
+
+ /*
+ * If there isn't a port here, don't do anything further.
+ */
+ if (!port->iobase && !port->mapbase && !port->membase)
+ return -ENXIO;
+
+ /*
+ * Now do the auto configuration stuff. Note that config_port
+ * is expected to claim the resources and map the port for us.
+ */
+ flags = 0;
+ if (port->flags & UPF_BOOT_AUTOCONF) {
+ if (!(port->flags & UPF_FIXED_TYPE)) {
+ port->type = PORT_UNKNOWN;
+ flags |= UART_CONFIG_TYPE;
+ }
+ port->ops->config_port(port, flags);
+ }
+
+ if (port->type != PORT_UNKNOWN) {
+ unsigned long flags;
+
+ pr_info("%s%d %s\n", drv->dev_name, port->line,
+ port->ops->type ? port->ops->type(port) : "");
+
+ /* Power up port for set_mctrl() */
+ uart_change_pm(state, UART_PM_STATE_ON);
+
+ /*
+ * Ensure that the modem control lines are de-activated.
+ * keep the DTR setting that is set in uart_set_options()
+ * We probably don't need a spinlock around this, but
+ */
+ spin_lock_irqsave(&port->lock, flags);
+ port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+ * If this driver supports console, and it hasn't been
+ * successfully registered yet, try to re-register it.
+ * It may be that the port was not available.
+ */
+ if (port->cons && !(port->cons->flags & CON_ENABLED))
+ register_console(port->cons);
+
+ /*
+ * Power down all ports by default, except the
+ * console if we have one.
+ */
+ if (!uart_console(port))
+ uart_change_pm(state, UART_PM_STATE_OFF);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/**
+* uart_add_one_port - attach a driver-defined port structure
+* @drv: pointer to the uart low level driver structure for this port
+* @port: uart port structure to use for this port.
+*/
+int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
+{
+ unsigned int index = port->line;
+ dev_t devt = MKDEV(drv->major, drv->minor) + index;
+ struct minitty_data *mtty;
+ struct uart_state *state;
+ int ret;
+
+ mtty = container_of(drv->state, typeof(*mtty), state) + index;
+ state = &mtty->state;
+
+ state->uart_port = port;
+ state->pm_state = UART_PM_STATE_UNDEFINED;
+ port->state = state;
+ port->cons = drv->cons;
+ port->minor = drv->minor + index;
+ uart_port_lock_init(port);
+
+ /* our default termios */
+ mtty->termios.c_iflag = ICRNL;
+ mtty->termios.c_oflag = OPOST | ONLCR;
+ mtty->termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ mtty->termios.c_lflag = ICANON | ECHO | ECHOE | ECHOK | ECHOKE | ECHOCTL;
+ mtty->termios.c_ispeed = 9600;
+ mtty->termios.c_ospeed = 9600;
+ memcpy(mtty->termios.c_cc, INIT_C_CC, sizeof(cc_t)*NCCS);
+
+ mutex_init(&mtty->mutex);
+ init_waitqueue_head(&mtty->write_wait);
+ init_waitqueue_head(&mtty->read_wait);
+ INIT_WORK(&mtty->rx_work, uart_rx_work);
+
+ if (port->cons && port->dev)
+ of_console_check(port->dev->of_node, port->cons->name, index);
+
+ ret = uart_configure_port(drv, state, port);
+ /*
+ * We don't support setserial so no point registering a nonexistent
+ * device . Silently ignore this port if not present.
+ */
+ if (ret) {
+ ret = 0;
+ goto out;
+ }
+
+ state->port.console = uart_console(port);
+
+ cdev_init(&mtty->cdev, &minitty_fops);
+ mtty->cdev.owner = drv->owner;
+ ret = cdev_add(&mtty->cdev, devt, 1);
+ if (ret)
+ goto out;
+ mtty->dev = device_create(minitty_class, port->dev, devt, mtty,
+ "%s%d", drv->dev_name, index);
+ if (IS_ERR(mtty->dev)) {
+ ret = PTR_ERR(mtty->dev);
+ goto err_cdev_del;
+ }
+
+ return 0;
+
+err_cdev_del:
+ cdev_del(&mtty->cdev);
+out:
+ return ret;
+}
+EXPORT_SYMBOL(uart_add_one_port);
+
+/**
+* uart_remove_one_port - detach a driver defined port structure
+* @drv: pointer to the uart low level driver structure for this port
+* @port: uart port structure for this port
+*
+* This unhooks the specified port structure from the core driver.
+* No further calls will be made to the low-level code for this port.
+*/
+int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
+{
+ unsigned int index = port->line;
+ dev_t devt = MKDEV(drv->major, drv->minor) + index;
+ struct minitty_data *mtty;
+ struct uart_state *state;
+
+ mtty = container_of(drv->state, typeof(*mtty), state) + index;
+ state = &mtty->state;
+ BUG_ON(state != port->state);
+
+ device_destroy(minitty_class, devt);
+ cdev_del(&mtty->cdev);
+
+ if (uart_console(port))
+ unregister_console(port->cons);
+
+ if (port->type != PORT_UNKNOWN && port->ops->release_port)
+ port->ops->release_port(port);
+ port->type = PORT_UNKNOWN;
+ state->uart_port = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL(uart_remove_one_port);
+
+/**
+* uart_register_driver - register a driver with the uart core layer
+* @drv: low level driver structure
+*
+* Register a uart driver. The per-port structures should be
+* registered using uart_add_one_port after this call has succeeded.
+*/
+int uart_register_driver(struct uart_driver *drv)
+{
+ struct minitty_data *mtty;
+ int ret;
+
+ BUG_ON(drv->state);
+
+ mtty = kzalloc(sizeof(*mtty) * drv->nr, GFP_KERNEL);
+ if (!mtty)
+ return -ENOMEM;
+
+ if (!drv->major) {
+ dev_t devt;
+ ret = alloc_chrdev_region(&devt, drv->minor, drv->nr, drv->driver_name);
+ drv->major = MAJOR(devt);
+ drv->minor = MINOR(devt);
+ } else {
+ dev_t devt = MKDEV(drv->major, drv->minor);
+ ret = register_chrdev_region(devt, drv->nr, drv->driver_name);
+ }
+ if (ret < 0)
+ goto err;
+
+ drv->state = &mtty->state;
+ return 0;
+
+err:
+ kfree(mtty);
+ return ret;
+}
+EXPORT_SYMBOL(uart_register_driver);
+
+/**
+* uart_unregister_driver - remove a driver from the uart core layer
+* @drv: low level driver structure
+*
+* Remove all references to a driver from the core driver. The low
+* level driver must have removed all its ports via the
+* uart_remove_one_port() if it registered them with uart_add_one_port().
+*/
+void uart_unregister_driver(struct uart_driver *drv)
+{
+ dev_t devt = MKDEV(drv->major, drv->minor);
+ struct minitty_data *mtty;
+
+ unregister_chrdev_region(devt, drv->nr);
+ mtty = container_of(drv->state, typeof(*mtty), state);
+ drv->state = NULL;
+ kfree(mtty);
+}
+EXPORT_SYMBOL(uart_unregister_driver);
+
+struct tty_struct *tty_port_tty_get(struct tty_port *port)
+{
+ return NULL;
+}
+EXPORT_SYMBOL(tty_port_tty_get);
+
+void do_SAK(struct tty_struct *tty)
+{
+}
+EXPORT_SYMBOL(do_SAK);
+
+struct tty_driver *uart_console_device(struct console *co, int *index)
+{
+ return NULL;
+}
+
+static struct cdev console_cdev;
+
+static char *minitty_devnode(struct device *dev, umode_t *mode)
+{
+ if (!mode)
+ return NULL;
+ if (dev->devt == MKDEV(TTYAUX_MAJOR, 0) ||
+ dev->devt == MKDEV(TTYAUX_MAJOR, 2))
+ *mode = 0666;
+ return NULL;
+}
+
+static int __init minitty_class_init(void)
+{
+ minitty_class = class_create(THIS_MODULE, "tty");
+ if (IS_ERR(minitty_class))
+ return PTR_ERR(minitty_class);
+ minitty_class->devnode = minitty_devnode;
+ return 0;
+}
+postcore_initcall(minitty_class_init);
+
+int __init minitty_init(void)
+{
+ dev_t devt = MKDEV(TTYAUX_MAJOR, 1);
+ cdev_init(&console_cdev, &minitty_fops);
+ if (cdev_add(&console_cdev, devt, 1) ||
+ register_chrdev_region(devt, 1, "/dev/console") < 0)
+ panic("Couldn't register /dev/console driver\n");
+ device_create(minitty_class, NULL, devt, NULL, "console");
+ return 0;
+}
+device_initcall(minitty_init);
\ No newline at end of file
diff --git a/drivers/tty/serial/serial_lib.c b/drivers/tty/serial/serial_lib.c
new file mode 100644
index 00000000..3c6ef6dd
--- /dev/null
+++ b/drivers/tty/serial/serial_lib.c
@@ -0,0 +1,440 @@
+/*
+ * Common support functions for serial port drivers
+ *
+ * Copyright 1999 ARM Limited
+ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/export.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/serial_core.h>
+#include <linux/spinlock.h>
+
+/*
+ * lockdep: port->lock is initialized in two places, but we
+ * want only one lock-class:
+ */
+static struct lock_class_key port_lock_key;
+
+void uart_port_lock_init(struct uart_port *port)
+{
+ /*
+ * If this port is a console, then the spinlock is already
+ * initialised.
+ */
+ if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) {
+ spin_lock_init(&port->lock);
+ lockdep_set_class(&port->lock, &port_lock_key);
+ }
+}
+
+/**
+ * uart_update_timeout - update per-port FIFO timeout.
+ * @port: uart_port structure describing the port
+ * @cflag: termios cflag value
+ * @baud: speed of the port
+ *
+ * Set the port FIFO timeout value. The @cflag value should
+ * reflect the actual hardware settings.
+ */
+void
+uart_update_timeout(struct uart_port *port, unsigned int cflag,
+ unsigned int baud)
+{
+ unsigned int bits;
+
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5:
+ bits = 7;
+ break;
+ case CS6:
+ bits = 8;
+ break;
+ case CS7:
+ bits = 9;
+ break;
+ default:
+ bits = 10;
+ break; /* CS8 */
+ }
+
+ if (cflag & CSTOPB)
+ bits++;
+ if (cflag & PARENB)
+ bits++;
+
+ /*
+ * The total number of bits to be transmitted in the fifo.
+ */
+ bits = bits * port->fifosize;
+
+ /*
+ * Figure the timeout to send the above number of bits.
+ * Add .02 seconds of slop
+ */
+ port->timeout = (HZ * bits) / baud + HZ/50;
+}
+EXPORT_SYMBOL(uart_update_timeout);
+
+/**
+ * uart_get_baud_rate - return baud rate for a particular port
+ * @port: uart_port structure describing the port in question.
+ * @termios: desired termios settings.
+ * @old: old termios (or NULL)
+ * @min: minimum acceptable baud rate
+ * @max: maximum acceptable baud rate
+ *
+ * Decode the termios structure into a numeric baud rate,
+ * taking account of the magic 38400 baud rate (with spd_*
+ * flags), and mapping the %B0 rate to 9600 baud.
+ *
+ * If the new baud rate is invalid, try the old termios setting.
+ * If it's still invalid, we try 9600 baud.
+ *
+ * Update the @termios structure to reflect the baud rate
+ * we're actually going to be using. Don't do this for the case
+ * where B0 is requested ("hang up").
+ */
+unsigned int
+uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old, unsigned int min, unsigned int max)
+{
+ unsigned int try;
+ unsigned int baud;
+ unsigned int altbaud;
+ int hung_up = 0;
+ upf_t flags = port->flags & UPF_SPD_MASK;
+
+ switch (flags) {
+ case UPF_SPD_HI:
+ altbaud = 57600;
+ break;
+ case UPF_SPD_VHI:
+ altbaud = 115200;
+ break;
+ case UPF_SPD_SHI:
+ altbaud = 230400;
+ break;
+ case UPF_SPD_WARP:
+ altbaud = 460800;
+ break;
+ default:
+ altbaud = 38400;
+ break;
+ }
+
+ for (try = 0; try < 2; try++) {
+ baud = tty_termios_baud_rate(termios);
+
+ /*
+ * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
+ * Die! Die! Die!
+ */
+ if (try == 0 && baud == 38400)
+ baud = altbaud;
+
+ /*
+ * Special case: B0 rate.
+ */
+ if (baud == 0) {
+ hung_up = 1;
+ baud = 9600;
+ }
+
+ if (baud >= min && baud <= max)
+ return baud;
+
+ /*
+ * Oops, the quotient was zero. Try again with
+ * the old baud rate if possible.
+ */
+ termios->c_cflag &= ~CBAUD;
+ if (old) {
+ baud = tty_termios_baud_rate(old);
+ if (!hung_up)
+ tty_termios_encode_baud_rate(termios,
+ baud, baud);
+ old = NULL;
+ continue;
+ }
+
+ /*
+ * As a last resort, if the range cannot be met then clip to
+ * the nearest chip supported rate.
+ */
+ if (!hung_up) {
+ if (baud <= min)
+ tty_termios_encode_baud_rate(termios,
+ min + 1, min + 1);
+ else
+ tty_termios_encode_baud_rate(termios,
+ max - 1, max - 1);
+ }
+ }
+ /* Should never happen */
+ WARN_ON(1);
+ return 0;
+}
+EXPORT_SYMBOL(uart_get_baud_rate);
+
+/**
+ * uart_get_divisor - return uart clock divisor
+ * @port: uart_port structure describing the port.
+ * @baud: desired baud rate
+ *
+ * Calculate the uart clock divisor for the port.
+ */
+unsigned int
+uart_get_divisor(struct uart_port *port, unsigned int baud)
+{
+ unsigned int quot;
+
+ /*
+ * Old custom speed handling.
+ */
+ if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
+ quot = port->custom_divisor;
+ else
+ quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
+
+ return quot;
+}
+EXPORT_SYMBOL(uart_get_divisor);
+
+#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
+/**
+ * uart_console_write - write a console message to a serial port
+ * @port: the port to write the message
+ * @s: array of characters
+ * @count: number of characters in string to write
+ * @putchar: function to write character to port
+ */
+void uart_console_write(struct uart_port *port, const char *s,
+ unsigned int count,
+ void (*putchar)(struct uart_port *, int))
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++, s++) {
+ if (*s == '\n')
+ putchar(port, '\r');
+ putchar(port, *s);
+ }
+}
+EXPORT_SYMBOL_GPL(uart_console_write);
+
+/*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+struct uart_port * __init
+uart_get_console(struct uart_port *ports, int nr, struct console *co)
+{
+ int idx = co->index;
+
+ if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 &&
+ ports[idx].membase == NULL))
+ for (idx = 0; idx < nr; idx++)
+ if (ports[idx].iobase != 0 ||
+ ports[idx].membase != NULL)
+ break;
+
+ co->index = idx;
+
+ return ports + idx;
+}
+
+/**
+ * uart_parse_earlycon - Parse earlycon options
+ * @p: ptr to 2nd field (ie., just beyond '<name>,')
+ * @iotype: ptr for decoded iotype (out)
+ * @addr: ptr for decoded mapbase/iobase (out)
+ * @options: ptr for <options> field; NULL if not present (out)
+ *
+ * Decodes earlycon kernel command line parameters of the form
+ * earlycon=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
+ * console=<name>,io|mmio|mmio16|mmio32|mmio32be|mmio32native,<addr>,<options>
+ *
+ * The optional form
+ * earlycon=<name>,0x<addr>,<options>
+ * console=<name>,0x<addr>,<options>
+ * is also accepted; the returned @iotype will be UPIO_MEM.
+ *
+ * Returns 0 on success or -EINVAL on failure
+ */
+int uart_parse_earlycon(char *p, unsigned char *iotype, resource_size_t *addr,
+ char **options)
+{
+ if (strncmp(p, "mmio,", 5) == 0) {
+ *iotype = UPIO_MEM;
+ p += 5;
+ } else if (strncmp(p, "mmio16,", 7) == 0) {
+ *iotype = UPIO_MEM16;
+ p += 7;
+ } else if (strncmp(p, "mmio32,", 7) == 0) {
+ *iotype = UPIO_MEM32;
+ p += 7;
+ } else if (strncmp(p, "mmio32be,", 9) == 0) {
+ *iotype = UPIO_MEM32BE;
+ p += 9;
+ } else if (strncmp(p, "mmio32native,", 13) == 0) {
+ *iotype = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
+ UPIO_MEM32BE : UPIO_MEM32;
+ p += 13;
+ } else if (strncmp(p, "io,", 3) == 0) {
+ *iotype = UPIO_PORT;
+ p += 3;
+ } else if (strncmp(p, "0x", 2) == 0) {
+ *iotype = UPIO_MEM;
+ } else {
+ return -EINVAL;
+ }
+
+ /*
+ * Before you replace it with kstrtoull(), think about options separator
+ * (',') it will not tolerate
+ */
+ *addr = simple_strtoull(p, NULL, 0);
+ p = strchr(p, ',');
+ if (p)
+ p++;
+
+ *options = p;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(uart_parse_earlycon);
+
+/**
+ * uart_parse_options - Parse serial port baud/parity/bits/flow control.
+ * @options: pointer to option string
+ * @baud: pointer to an 'int' variable for the baud rate.
+ * @parity: pointer to an 'int' variable for the parity.
+ * @bits: pointer to an 'int' variable for the number of data bits.
+ * @flow: pointer to an 'int' variable for the flow control character.
+ *
+ * uart_parse_options decodes a string containing the serial console
+ * options. The format of the string is <baud><parity><bits><flow>,
+ * eg: 115200n8r
+ */
+void
+uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow)
+{
+ char *s = options;
+
+ *baud = simple_strtoul(s, NULL, 10);
+ while (*s >= '0' && *s <= '9')
+ s++;
+ if (*s)
+ *parity = *s++;
+ if (*s)
+ *bits = *s++ - '0';
+ if (*s)
+ *flow = *s;
+}
+EXPORT_SYMBOL_GPL(uart_parse_options);
+
+/**
+ * uart_set_options - setup the serial console parameters
+ * @port: pointer to the serial ports uart_port structure
+ * @co: console pointer
+ * @baud: baud rate
+ * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even)
+ * @bits: number of data bits
+ * @flow: flow control character - 'r' (rts)
+ */
+int
+uart_set_options(struct uart_port *port, struct console *co,
+ int baud, int parity, int bits, int flow)
+{
+ struct ktermios termios;
+ static struct ktermios dummy;
+
+ /*
+ * Ensure that the serial console lock is initialised
+ * early.
+ */
+ uart_port_lock_init(port);
+
+ memset(&termios, 0, sizeof(struct ktermios));
+
+ termios.c_cflag |= CREAD | HUPCL | CLOCAL;
+ tty_termios_encode_baud_rate(&termios, baud, baud);
+
+ if (bits == 7)
+ termios.c_cflag |= CS7;
+ else
+ termios.c_cflag |= CS8;
+
+ switch (parity) {
+ case 'o': case 'O':
+ termios.c_cflag |= PARODD;
+ /*fall through*/
+ case 'e': case 'E':
+ termios.c_cflag |= PARENB;
+ break;
+ }
+
+ if (flow == 'r')
+ termios.c_cflag |= CRTSCTS;
+
+ /*
+ * some uarts on other side don't support no flow control.
+ * So we set * DTR in host uart to make them happy
+ */
+ port->mctrl |= TIOCM_DTR;
+
+ port->ops->set_termios(port, &termios, &dummy);
+ /*
+ * Allow the setting of the UART parameters with a NULL console
+ * too:
+ */
+ if (co)
+ co->cflag = termios.c_cflag;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(uart_set_options);
+#endif /* CONFIG_SERIAL_CORE_CONSOLE */
+
+/*
+ * Are the two ports equivalent?
+ */
+int uart_match_port(struct uart_port *port1, struct uart_port *port2)
+{
+ if (port1->iotype != port2->iotype)
+ return 0;
+
+ switch (port1->iotype) {
+ case UPIO_PORT:
+ return (port1->iobase == port2->iobase);
+ case UPIO_HUB6:
+ return (port1->iobase == port2->iobase) &&
+ (port1->hub6 == port2->hub6);
+ case UPIO_MEM:
+ case UPIO_MEM16:
+ case UPIO_MEM32:
+ case UPIO_MEM32BE:
+ case UPIO_AU:
+ case UPIO_TSI:
+ return (port1->mapbase == port2->mapbase);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(uart_match_port);
\ No newline at end of file
diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c
new file mode 100644
index 00000000..eeab3ea3
--- /dev/null
+++ b/drivers/tty/tty_baudrate.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/export.h>
+
+
+/*
+ * Routine which returns the baud rate of the tty
+ *
+ * Note that the baud_table needs to be kept in sync with the
+ * include/asm/termbits.h file.
+ */
+static const speed_t baud_table[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800,
+#ifdef __sparc__
+ 76800, 153600, 307200, 614400, 921600
+#else
+ 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
+ 2500000, 3000000, 3500000, 4000000
+#endif
+};
+
+#ifndef __sparc__
+static const tcflag_t baud_bits[] = {
+ B0, B50, B75, B110, B134, B150, B200, B300, B600,
+ B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+ B57600, B115200, B230400, B460800, B500000, B576000,
+ B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
+ B3000000, B3500000, B4000000
+};
+#else
+static const tcflag_t baud_bits[] = {
+ B0, B50, B75, B110, B134, B150, B200, B300, B600,
+ B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+ B57600, B115200, B230400, B460800, B76800, B153600,
+ B307200, B614400, B921600
+};
+#endif
+
+static int n_baud_table = ARRAY_SIZE(baud_table);
+
+/**
+ * tty_termios_baud_rate
+ * @termios: termios structure
+ *
+ * Convert termios baud rate data into a speed. This should be called
+ * with the termios lock held if this termios is a terminal termios
+ * structure. May change the termios data. Device drivers can call this
+ * function but should use ->c_[io]speed directly as they are updated.
+ *
+ * Locking: none
+ */
+
+speed_t tty_termios_baud_rate(struct ktermios *termios)
+{
+ unsigned int cbaud;
+
+ cbaud = termios->c_cflag & CBAUD;
+
+#ifdef BOTHER
+ /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
+ if (cbaud == BOTHER)
+ return termios->c_ospeed;
+#endif
+ if (cbaud & CBAUDEX) {
+ cbaud &= ~CBAUDEX;
+
+ if (cbaud < 1 || cbaud + 15 > n_baud_table)
+ termios->c_cflag &= ~CBAUDEX;
+ else
+ cbaud += 15;
+ }
+ return baud_table[cbaud];
+}
+EXPORT_SYMBOL(tty_termios_baud_rate);
+
+/**
+ * tty_termios_input_baud_rate
+ * @termios: termios structure
+ *
+ * Convert termios baud rate data into a speed. This should be called
+ * with the termios lock held if this termios is a terminal termios
+ * structure. May change the termios data. Device drivers can call this
+ * function but should use ->c_[io]speed directly as they are updated.
+ *
+ * Locking: none
+ */
+
+speed_t tty_termios_input_baud_rate(struct ktermios *termios)
+{
+#ifdef IBSHIFT
+ unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
+
+ if (cbaud == B0)
+ return tty_termios_baud_rate(termios);
+
+ /* Magic token for arbitrary speed via c_ispeed*/
+ if (cbaud == BOTHER)
+ return termios->c_ispeed;
+
+ if (cbaud & CBAUDEX) {
+ cbaud &= ~CBAUDEX;
+
+ if (cbaud < 1 || cbaud + 15 > n_baud_table)
+ termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
+ else
+ cbaud += 15;
+ }
+ return baud_table[cbaud];
+#else
+ return tty_termios_baud_rate(termios);
+#endif
+}
+EXPORT_SYMBOL(tty_termios_input_baud_rate);
+
+/**
+ * tty_termios_encode_baud_rate
+ * @termios: ktermios structure holding user requested state
+ * @ispeed: input speed
+ * @ospeed: output speed
+ *
+ * Encode the speeds set into the passed termios structure. This is
+ * used as a library helper for drivers so that they can report back
+ * the actual speed selected when it differs from the speed requested
+ *
+ * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
+ * we need to carefully set the bits when the user does not get the
+ * desired speed. We allow small margins and preserve as much of possible
+ * of the input intent to keep compatibility.
+ *
+ * Locking: Caller should hold termios lock. This is already held
+ * when calling this function from the driver termios handler.
+ *
+ * The ifdefs deal with platforms whose owners have yet to update them
+ * and will all go away once this is done.
+ */
+
+void tty_termios_encode_baud_rate(struct ktermios *termios,
+ speed_t ibaud, speed_t obaud)
+{
+ int i = 0;
+ int ifound = -1, ofound = -1;
+ int iclose = ibaud/50, oclose = obaud/50;
+ int ibinput = 0;
+
+ if (obaud == 0) /* CD dropped */
+ ibaud = 0; /* Clear ibaud to be sure */
+
+ termios->c_ispeed = ibaud;
+ termios->c_ospeed = obaud;
+
+#ifdef BOTHER
+ /* If the user asked for a precise weird speed give a precise weird
+ answer. If they asked for a Bfoo speed they may have problems
+ digesting non-exact replies so fuzz a bit */
+
+ if ((termios->c_cflag & CBAUD) == BOTHER)
+ oclose = 0;
+ if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
+ iclose = 0;
+ if ((termios->c_cflag >> IBSHIFT) & CBAUD)
+ ibinput = 1; /* An input speed was specified */
+#endif
+ termios->c_cflag &= ~CBAUD;
+
+ /*
+ * Our goal is to find a close match to the standard baud rate
+ * returned. Walk the baud rate table and if we get a very close
+ * match then report back the speed as a POSIX Bxxxx value by
+ * preference
+ */
+
+ do {
+ if (obaud - oclose <= baud_table[i] &&
+ obaud + oclose >= baud_table[i]) {
+ termios->c_cflag |= baud_bits[i];
+ ofound = i;
+ }
+ if (ibaud - iclose <= baud_table[i] &&
+ ibaud + iclose >= baud_table[i]) {
+ /* For the case input == output don't set IBAUD bits
+ if the user didn't do so */
+ if (ofound == i && !ibinput)
+ ifound = i;
+#ifdef IBSHIFT
+ else {
+ ifound = i;
+ termios->c_cflag |= (baud_bits[i] << IBSHIFT);
+ }
+#endif
+ }
+ } while (++i < n_baud_table);
+
+ /*
+ * If we found no match then use BOTHER if provided or warn
+ * the user their platform maintainer needs to wake up if not.
+ */
+#ifdef BOTHER
+ if (ofound == -1)
+ termios->c_cflag |= BOTHER;
+ /* Set exact input bits only if the input and output differ or the
+ user already did */
+ if (ifound == -1 && (ibaud != obaud || ibinput))
+ termios->c_cflag |= (BOTHER << IBSHIFT);
+#else
+ if (ifound == -1 || ofound == -1)
+ pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
+#endif
+}
+EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
+
+/**
+ * tty_encode_baud_rate - set baud rate of the tty
+ * @ibaud: input baud rate
+ * @obad: output baud rate
+ *
+ * Update the current termios data for the tty with the new speed
+ * settings. The caller must hold the termios_rwsem for the tty in
+ * question.
+ */
+
+void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
+{
+ tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
+}
+EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
\ No newline at end of file
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 789c8148..de9fb884 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3583,30 +3583,6 @@ void tty_default_fops(struct file_operations *fops)
*fops = tty_fops;
}
-/*
- * Initialize the console device. This is called *early*, so
- * we can't necessarily depend on lots of kernel help here.
- * Just do some early initializations, and do the complex setup
- * later.
- */
-void __init console_init(void)
-{
- initcall_t *call;
-
- /* Setup the default TTY line discipline. */
- n_tty_init();
-
- /*
- * set up the console device so that later boot sequences can
- * inform about problems etc..
- */
- call = __con_initcall_start;
- while (call < __con_initcall_end) {
- (*call)();
- call++;
- }
-}
-
static char *tty_devnode(struct device *dev, umode_t *mode)
{
if (!mode)
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index bf36ac9a..a43d7ef0 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -258,6 +258,7 @@ static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old)
/* FIXME: What should we do for i/ospeed */
}
+#if 0
/*
* Routine which returns the baud rate of the tty
*
@@ -479,6 +480,7 @@ void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
}
EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
+#endif
/**
* tty_termios_copy_hw - copy hardware settings
diff --git a/drivers/tty/vt/Makefile b/drivers/tty/vt/Makefile
index 17ae94cb..d0c22be1 100644
--- a/drivers/tty/vt/Makefile
+++ b/drivers/tty/vt/Makefile
@@ -5,6 +5,7 @@ FONTMAPFILE = cp437.uni
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \
selection.o keyboard.o
+obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
diff --git a/drivers/tty/vt/dummycon.c b/drivers/tty/vt/dummycon.c
new file mode 100644
index 00000000..b90ef96e
--- /dev/null
+++ b/drivers/tty/vt/dummycon.c
@@ -0,0 +1,73 @@
+/*
+ * linux/drivers/video/dummycon.c -- A dummy console driver
+ *
+ * To be used if there's no other console driver (e.g. for plain VGA text)
+ * available, usually until fbcon takes console over.
+ */
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include <linux/screen_info.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+/*
+ * Dummy console driver
+ */
+
+#if defined(__arm__)
+#define DUMMY_COLUMNS screen_info.orig_video_cols
+#define DUMMY_ROWS screen_info.orig_video_lines
+#else
+/* set by Kconfig. Use 80x25 for 640x480 and 160x64 for 1280x1024 */
+#define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS
+#define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS
+#endif
+
+static const char *dummycon_startup(void)
+{
+ return "dummy device";
+}
+
+static void dummycon_init(struct vc_data *vc, int init)
+{
+ vc->vc_can_do_color = 1;
+ if (init) {
+ vc->vc_cols = DUMMY_COLUMNS;
+ vc->vc_rows = DUMMY_ROWS;
+ } else
+ vc_resize(vc, DUMMY_COLUMNS, DUMMY_ROWS);
+}
+
+static int dummycon_dummy(void)
+{
+ return 0;
+}
+
+#define DUMMY (void *)dummycon_dummy
+
+/*
+ * The console `switch' structure for the dummy console
+ *
+ * Most of the operations are dummies.
+ */
+
+const struct consw dummy_con = {
+ .owner = THIS_MODULE,
+ .con_startup = dummycon_startup,
+ .con_init = dummycon_init,
+ .con_deinit = DUMMY,
+ .con_clear = DUMMY,
+ .con_putc = DUMMY,
+ .con_putcs = DUMMY,
+ .con_cursor = DUMMY,
+ .con_scroll = DUMMY,
+ .con_switch = DUMMY,
+ .con_blank = DUMMY,
+ .con_font_set = DUMMY,
+ .con_font_default = DUMMY,
+ .con_font_copy = DUMMY,
+};
+EXPORT_SYMBOL_GPL(dummy_con);
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index 5ef8da6e..f82a342d 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -18,6 +18,9 @@
#include <linux/usb/of.h>
#include <linux/usb/otg.h>
#include <linux/of_platform.h>
+#ifndef CONFIG_USE_OF
+#include <mach/fh_usb_plat.h>
+#endif
const char *usb_otg_state_string(enum usb_otg_state state)
{
@@ -115,6 +118,7 @@ static enum usb_dr_mode usb_get_dr_mode_from_string(const char *str)
enum usb_dr_mode usb_get_dr_mode(struct device *dev)
{
+#ifdef CONFIG_USE_OF
const char *dr_mode;
int err;
@@ -123,10 +127,36 @@ enum usb_dr_mode usb_get_dr_mode(struct device *dev)
return USB_DR_MODE_UNKNOWN;
return usb_get_dr_mode_from_string(dr_mode);
+#else
+ struct fh_usb_platform_data *plat_data
+ = (struct fh_usb_platform_data *)dev_get_platdata(dev);
+
+ return usb_get_dr_mode_from_string(plat_data->dr_mode);
+#endif
}
EXPORT_SYMBOL_GPL(usb_get_dr_mode);
-#ifdef CONFIG_OF
+u32 usb_get_vbus_pwren_gpio(struct device *dev)
+{
+#ifdef CONFIG_USE_OF
+ u32 pwren_gpio;
+ int err;
+
+ err = device_property_read_u32(dev, "vbus_pwren", &pwren_gpio);
+ if (err < 0)
+ return 0xFFFFFFFF;
+ else
+ return pwren_gpio;
+#else
+ struct fh_usb_platform_data *plat_data
+ = (struct fh_usb_platform_data *)dev_get_platdata(dev);
+
+ return plat_data->vbus_pwren;
+#endif
+}
+EXPORT_SYMBOL_GPL(usb_get_vbus_pwren_gpio);
+
+#ifdef CONFIG_USE_OF
/**
* of_usb_get_dr_mode_by_phy - Get dual role mode for the controller device
* which is associated with the given phy device_node
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index e838701d..b754a454 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -52,6 +52,14 @@ config USB_DWC2_DUAL_ROLE
option requires USB_GADGET to be enabled.
endchoice
+config USB_DWC2_VBVALIDOVEN
+ bool "Enable VBUS Valid Override"
+ depends on USB_DWC2_HOST || USB_DWC2_DUAL_ROLE
+ default n
+ help
+ Say Y here to override the vbus-valid signal received from the PHY.
+ In one word, this feature is used to ignor the vbus overcurrent.
+
config USB_DWC2_PCI
tristate "DWC2 PCI"
depends on PCI
@@ -92,4 +100,29 @@ config USB_DWC2_DEBUG_PERIODIC
non-periodic transfers, but of course the debug logs will be
incomplete. Note that this also disables some debug messages
for which the transfer type cannot be deduced.
+
+config USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC
+ bool "Enable Qtd Dynamic Adjust While Host Dma Desc Enabled"
+ depends on USB_DWC2_HOST
+ default n
+ help
+ Say Y here to enable qtd dynamic adjust to adapt the varied
+ usbnet environment and then reach higher performance accordingly
+ while host dma desc enabled.
+
+config USB_DWC2_DMA
+ bool "Enable DMA Mode"
+ default y
+ help
+ Say Y here to enable DMA mode for accessing the data FIFOs.
+
+config USB_DWC2_DMA_DESC
+ bool "Use Descriptor DMA Mode"
+ depends on USB_DWC2_DMA
+ default n
+ help
+ Say Y here to enable the descriptor DMA mode for accessing
+ the data FIFOs when DMA mode is enabled.
+ WARNING: Say N here to use address DMA mode.
+ If in doubt, say N.
endif
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index f6759c61..7e22da59 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -1187,6 +1187,10 @@ void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg, int val)
}
hsotg->core_params->phy_utmi_width = val;
+ if (val == 8)
+ hsotg->phyif = GUSBCFG_PHYIF8;
+ else
+ hsotg->phyif = GUSBCFG_PHYIF16;
}
void dwc2_set_param_ulpi_fs_ls(struct dwc2_hsotg *hsotg, int val)
@@ -1518,7 +1522,8 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
*/
hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID);
if ((hw->snpsid & 0xfffff000) != 0x4f542000 &&
- (hw->snpsid & 0xfffff000) != 0x4f543000) {
+ (hw->snpsid & 0xfffff000) != 0x4f543000 &&
+ (hw->snpsid & 0xfffff000) != 0x4f544000) {
dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
hw->snpsid);
return -ENODEV;
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 0f45a2f1..a040d268 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -263,9 +263,13 @@ enum dwc2_lx_state {
* Gadget periodic tx fifo sizes as used by legacy driver
* EP0 is not included
*/
-#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \
- 768, 0, 0, 0, 0, 0, 0, 0}
-
+#ifdef CONFIG_USB_G_WEBCAM_PATCH
+#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {128, 768, 128, 128, 128, 32, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+#else
+#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 256, 32, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0}
+#endif
/* Gadget ep0 states */
enum dwc2_ep0_state {
DWC2_EP0_SETUP,
@@ -868,6 +872,7 @@ struct dwc2_hsotg {
void *priv;
int irq;
struct clk *clk;
+ struct clk *clk2;
struct reset_control *reset;
unsigned int queuing_high_bandwidth:1;
diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index d85c5c9f..bb8ff521 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -288,14 +288,9 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
/*
* Need to schedule a work, as there are possible DELAY function calls.
- * Release lock before scheduling workq as it holds spinlock during
- * scheduling.
*/
- if (hsotg->wq_otg) {
- spin_unlock(&hsotg->lock);
+ if (hsotg->wq_otg)
queue_work(hsotg->wq_otg, &hsotg->wf_otg);
- spin_lock(&hsotg->lock);
- }
}
/**
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3ae27b6e..0ed870d8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -34,6 +34,8 @@
#include "core.h"
#include "hw.h"
+static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
+ u32 bit, u32 timeout);
/* conversion functions */
static inline struct dwc2_hsotg_req *our_req(struct usb_request *req)
{
@@ -190,6 +192,7 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
unsigned int addr;
int timeout;
u32 val;
+ u16 fifodepth;
/* Reset fifo map if not correctly cleared during previous session */
WARN_ON(hsotg->fifo_map);
@@ -228,6 +231,10 @@ static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep));
}
+ fifodepth = (dwc2_readl(hsotg->regs + GHWCFG3)) >> 16;
+ if (addr >= fifodepth)
+ pr_err("error:fifo size(%d) > fifo depth =%d\n",
+ addr, fifodepth);
/*
* according to p428 of the design guide, we need to ensure that
* all fifos are flushed before continuing
@@ -494,8 +501,8 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep)
{
int index = hs_ep->index;
- unsigned maxsize;
- unsigned maxpkt;
+ unsigned int maxsize;
+ unsigned int maxpkt;
if (index != 0) {
maxsize = DXEPTSIZ_XFERSIZE_LIMIT + 1;
@@ -883,7 +890,10 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
while (dwc2_gadget_target_frame_elapsed(hs_ep))
dwc2_gadget_incr_frame_num(hs_ep);
- if (hs_ep->target_frame != TARGET_FRAME_INITIAL)
+ /* if (hs_ep->target_frame != TARGET_FRAME_INITIAL) */
+ /* change by mengqx */
+ if (hs_ep->target_frame != TARGET_FRAME_INITIAL ||
+ !hs_ep->dir_in)
dwc2_hsotg_start_req(hs, hs_ep, hs_req, false);
}
return 0;
@@ -2566,7 +2576,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
if (using_dma(hsotg))
dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
- (GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT),
+ (GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT),
hsotg->regs + GAHBCFG);
else
dwc2_writel(((hsotg->dedicated_fifos) ?
@@ -2698,9 +2708,14 @@ static void dwc2_gadget_handle_incomplete_isoc_in(struct dwc2_hsotg *hsotg)
epctrl = dwc2_readl(hsotg->regs + DIEPCTL(idx));
if ((epctrl & DXEPCTL_EPENA) && hs_ep->isochronous &&
dwc2_gadget_target_frame_elapsed(hs_ep)) {
+#ifdef CONFIG_USB_G_WEBCAM_PATCH
+ /* do nothing, change by mengqx */
+
+#else
epctrl |= DXEPCTL_SNAK;
epctrl |= DXEPCTL_EPDIS;
dwc2_writel(epctrl, hsotg->regs + DIEPCTL(idx));
+#endif
}
}
@@ -2736,6 +2751,9 @@ static void dwc2_gadget_handle_incomplete_isoc_out(struct dwc2_hsotg *hsotg)
epctrl = dwc2_readl(hsotg->regs + DOEPCTL(idx));
if ((epctrl & DXEPCTL_EPENA) && hs_ep->isochronous &&
dwc2_gadget_target_frame_elapsed(hs_ep)) {
+#ifdef CONFIG_USB_G_WEBCAM_PATCH
+ /* do nothing, change by mengqx */
+#else
/* Unmask GOUTNAKEFF interrupt */
gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
gintmsk |= GINTSTS_GOUTNAKEFF;
@@ -2744,6 +2762,7 @@ static void dwc2_gadget_handle_incomplete_isoc_out(struct dwc2_hsotg *hsotg)
gintsts = dwc2_readl(hsotg->regs + GINTSTS);
if (!(gintsts & GINTSTS_GOUTNAKEFF))
__orr32(hsotg->regs + DCTL, DCTL_SGOUTNAK);
+#endif
}
}
@@ -3106,6 +3125,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
int index = hs_ep->index;
unsigned long flags;
u32 epctrl_reg;
+ u32 epint_reg;
u32 ctrl;
dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
@@ -3116,6 +3136,8 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
}
epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
+ epint_reg = dir_in ? DIEPINT(hs_ep->index) :
+ DOEPINT(hs_ep->index);
spin_lock_irqsave(&hsotg->lock, flags);
@@ -3123,10 +3145,20 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
ctrl &= ~DXEPCTL_EPENA;
ctrl &= ~DXEPCTL_USBACTEP;
ctrl |= DXEPCTL_SNAK;
+ ctrl |= DXEPCTL_EPDIS; /* add by mengqx */
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
dwc2_writel(ctrl, hsotg->regs + epctrl_reg);
+ if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100)) {
+ dev_warn(hsotg->dev,
+ "%s: timeout DOEPCTL.EPDisable\n", __func__);
+ } else
+ dwc2_writel(DXEPINT_EPDISBLD, hsotg->regs + epint_reg);
+ /* add by mengqx */
+ if (dir_in)
+ dwc2_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
+
/* disable endpoint interrupts */
dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
@@ -3226,6 +3258,9 @@ static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
} else {
/* Remove global NAKs */
__bic32(hsotg->regs + DCTL, DCTL_SGOUTNAK);
+#ifdef CONFIG_USB_G_WEBCAM_PATCH
+ __orr32(hsotg->regs + DCTL, DCTL_CGOUTNAK);
+#endif
}
}
@@ -3802,7 +3837,7 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg)
#endif
}
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
static void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg)
{
struct device_node *np = hsotg->dev->of_node;
@@ -3860,9 +3895,11 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
int i;
u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE;
+ /* Initialize to DMA Buffer Mode as default */
+ hsotg->g_using_dma = 1;
/* Initialize to legacy fifo configuration values */
- hsotg->g_rx_fifo_sz = 2048;
- hsotg->g_np_g_tx_fifo_sz = 1024;
+ hsotg->g_rx_fifo_sz = 768;
+ hsotg->g_np_g_tx_fifo_sz = 256;
memcpy(&hsotg->g_tx_fifo_sz[1], p_tx_fifo, sizeof(p_tx_fifo));
/* Device tree specific probe */
dwc2_hsotg_of_probe(hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 984d6aae..06fb688a 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -943,6 +943,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
* (in the case of URB_DEQUEUE), so the channel needs to be
* shut down carefully to prevent crashes.
*/
+ int wtd = 10000;
u32 hcintmsk = HCINTMSK_CHHLTD;
dev_vdbg(hsotg->dev, "dequeue/error\n");
@@ -963,6 +964,11 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
chan->halt_status = halt_status;
hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
+ while (wtd--) {
+ if (!(hcchar & HCCHAR_CHENA))
+ break;
+ hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
+ }
if (!(hcchar & HCCHAR_CHENA)) {
/*
* The channel is either already halted or it hasn't
@@ -1425,19 +1431,20 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
if (num_packets > max_hc_pkt_count) {
num_packets = max_hc_pkt_count;
chan->xfer_len = num_packets * chan->max_packet;
+ } else if (chan->ep_is_in) {
+ /*
+ * Always program an integral # of max packets
+ * for IN transfers.
+ * Note: This assumes that the input buffer is
+ * aligned and sized accordingly.
+ */
+ chan->xfer_len = num_packets * chan->max_packet;
}
} else {
/* Need 1 packet for transfer length of 0 */
num_packets = 1;
}
- if (chan->ep_is_in)
- /*
- * Always program an integral # of max packets for IN
- * transfers
- */
- chan->xfer_len = num_packets * chan->max_packet;
-
if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
chan->ep_type == USB_ENDPOINT_XFER_ISOC)
/*
@@ -2344,6 +2351,14 @@ static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
otgctl &= ~GOTGCTL_HSTSETHNPEN;
dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
+#if IS_ENABLED(CONFIG_USB_DWC2_VBVALIDOVEN)
+ /* VBUS Valid Override Enable, VBUS Valid OverrideValue */
+ otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+ otgctl |= GOTGCTL_VBVALIDOVEN;
+ otgctl |= GOTGCTL_VBVALIDOVVAL;
+ dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
+#endif
+
if (hsotg->core_params->dma_desc_enable <= 0) {
int num_channels, i;
u32 hcchar;
@@ -2544,59 +2559,72 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
#define DWC2_USB_DMA_ALIGN 4
+struct dma_aligned_buffer {
+ void *old_xfer_buffer;
+ u8 data[0];
+};
+
static void dwc2_free_dma_aligned_buffer(struct urb *urb)
{
- void *stored_xfer_buffer;
+ struct dma_aligned_buffer *dma;
+ size_t length;
if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
return;
- /* Restore urb->transfer_buffer from the end of the allocated area */
- memcpy(&stored_xfer_buffer, urb->transfer_buffer +
- urb->transfer_buffer_length, sizeof(urb->transfer_buffer));
+ dma = container_of(urb->transfer_buffer,
+ struct dma_aligned_buffer, data);
- if (usb_urb_dir_in(urb))
- memcpy(stored_xfer_buffer, urb->transfer_buffer,
- urb->transfer_buffer_length);
- kfree(urb->transfer_buffer);
- urb->transfer_buffer = stored_xfer_buffer;
+ if (usb_urb_dir_in(urb)) {
+ if (usb_pipeisoc(urb->pipe))
+ length = urb->transfer_buffer_length;
+ else
+ length = urb->actual_length;
+
+ memcpy(dma->old_xfer_buffer, dma->data, length);
+ }
+ urb->transfer_buffer = dma->old_xfer_buffer;
+ kfree(dma);
urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
}
static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
{
- void *kmalloc_ptr;
+ struct dma_aligned_buffer *dma;
size_t kmalloc_size;
- if (urb->num_sgs || urb->sg ||
- urb->transfer_buffer_length == 0 ||
+ if (urb->num_sgs || urb->sg || urb->transfer_buffer_length == 0 ||
+ (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) ||
!((uintptr_t)urb->transfer_buffer & (DWC2_USB_DMA_ALIGN - 1)))
return 0;
- /*
- * Allocate a buffer with enough padding for original transfer_buffer
- * pointer. This allocation is guaranteed to be aligned properly for
- * DMA
- */
- kmalloc_size = urb->transfer_buffer_length +
- sizeof(urb->transfer_buffer);
+ kmalloc_size = sizeof(struct dma_aligned_buffer);
+ if (usb_urb_dir_out(urb)) {
+ kmalloc_size += urb->transfer_buffer_length;
+ } else {
+ struct usb_host_endpoint *ep = urb->ep;
+ int maxp = usb_endpoint_maxp(&ep->desc);
- kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
- if (!kmalloc_ptr)
- return -ENOMEM;
+ /*
+ * Input transfer buffer size must be a multiple of the
+ * endpoint's maximum packet size to match the transfer
+ * limit programmed into the chip.
+ * See calculation of chan->xfer_len in
+ * dwc2_hc_start_transfer().
+ */
+ kmalloc_size += roundup(urb->transfer_buffer_length, maxp);
+ }
- /*
- * Position value of original urb->transfer_buffer pointer to the end
- * of allocation for later referencing
- */
- memcpy(kmalloc_ptr + urb->transfer_buffer_length,
- &urb->transfer_buffer, sizeof(urb->transfer_buffer));
+ dma = kmalloc(kmalloc_size, mem_flags);
+ if (!dma)
+ return -ENOMEM;
+ dma->old_xfer_buffer = urb->transfer_buffer;
if (usb_urb_dir_out(urb))
- memcpy(kmalloc_ptr, urb->transfer_buffer,
+ memcpy(dma->data, urb->transfer_buffer,
urb->transfer_buffer_length);
- urb->transfer_buffer = kmalloc_ptr;
+ urb->transfer_buffer = dma->data;
urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
@@ -3624,6 +3652,10 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
goto error;
if (!hsotg->flags.b.port_connect_status) {
+ if (dwc2_is_host_mode(hsotg) &&
+ (dwc2_read_hprt0(hsotg) & HPRT0_PWR) == 0) {
+ dev_info(hsotg->dev, "power cycle should not be broken\n");
+ } else
/*
* The port is disconnected, which means the core is
* either in device mode or it soon will be. Just
@@ -4772,9 +4804,7 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
urb->hcpriv = NULL;
/* Higher layer software sets URB status */
- spin_unlock(&hsotg->lock);
usb_hcd_giveback_urb(hcd, urb, status);
- spin_lock(&hsotg->lock);
dev_dbg(hsotg->dev, "Called usb_hcd_giveback_urb()\n");
dev_dbg(hsotg->dev, " urb->status = %d\n", urb->status);
@@ -5174,6 +5204,10 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
/* Don't support SG list at this point */
hcd->self.sg_tablesize = 0;
+ /*copy phy to hcd add tangyh*/
+ hcd->usb_phy = hsotg->uphy;
+ hcd->phy = hsotg->phy;
+
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_host(hsotg->uphy->otg, &hcd->self);
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h
index 7758bfb6..9ba113a0 100644
--- a/drivers/usb/dwc2/hcd.h
+++ b/drivers/usb/dwc2/hcd.h
@@ -160,6 +160,10 @@ struct dwc2_host_chan {
dma_addr_t desc_list_addr;
u32 desc_list_sz;
struct list_head split_order_list_entry;
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ struct timeval qh_start;
+ struct timeval qh_end;
+#endif
};
struct dwc2_hcd_pipe_info {
@@ -358,6 +362,10 @@ struct dwc2_qh {
unsigned tt_buffer_dirty:1;
unsigned unreserve_pending:1;
unsigned schedule_low_speed:1;
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ struct timeval qh_dura;
+ int max_dma_desc_num_lastime;
+#endif
};
/**
diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c
index 0e1d42b5..759956ff 100644
--- a/drivers/usb/dwc2/hcd_ddma.c
+++ b/drivers/usb/dwc2/hcd_ddma.c
@@ -366,6 +366,13 @@ int dwc2_hcd_qh_init_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
}
qh->ntd = 0;
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ if (hsotg->core_params->dma_desc_enable
+ && qh->ep_type == USB_ENDPOINT_XFER_BULK
+ && qh->ep_is_in) {
+ qh->max_dma_desc_num_lastime = 1;
+ }
+#endif
return 0;
err1:
@@ -744,6 +751,71 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan = qh->channel;
int n_desc = 0;
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ int max_dma_desc_num_dynamic;
+ static int qtd_inc_statistic;
+
+ if (hsotg->core_params->dma_desc_enable
+ && chan->ep_type == USB_ENDPOINT_XFER_BULK
+ && chan->ep_is_in) {
+ if (qh->qh_dura.tv_sec != 0
+ || qh->qh_dura.tv_usec != 0) {
+ if (qh->qh_dura.tv_sec > 0) {
+ qtd_inc_statistic = 0;
+
+ max_dma_desc_num_dynamic
+ = qh->max_dma_desc_num_lastime
+ /qh->qh_dura.tv_sec;
+ if (max_dma_desc_num_dynamic == 0) {
+ if (qh->max_dma_desc_num_lastime > 2)
+ max_dma_desc_num_dynamic
+ = qh->max_dma_desc_num_lastime
+ / 2;
+ else
+ max_dma_desc_num_dynamic = 1;
+ }
+ } else if (qh->qh_dura.tv_usec > 0
+ && qh->qh_dura.tv_usec < 10000) {
+ qtd_inc_statistic++;
+ if (qtd_inc_statistic > 10) {
+ max_dma_desc_num_dynamic
+ = qh->max_dma_desc_num_lastime + 1;
+ if (max_dma_desc_num_dynamic
+ > MAX_DMA_DESC_NUM_GENERIC)
+ max_dma_desc_num_dynamic
+ = MAX_DMA_DESC_NUM_GENERIC;
+ } else {
+ max_dma_desc_num_dynamic
+ = qh->max_dma_desc_num_lastime;
+ }
+ } else {
+ qtd_inc_statistic = 0;
+
+ max_dma_desc_num_dynamic
+ = qh->max_dma_desc_num_lastime;
+ }
+
+ qh->qh_dura.tv_sec = 0;
+ qh->qh_dura.tv_usec = 0;
+ } else {
+ max_dma_desc_num_dynamic = MAX_DMA_DESC_NUM_GENERIC;
+ if (chan->qh_start.tv_sec != 0
+ || chan->qh_start.tv_usec != 0
+ || chan->qh_end.tv_sec != 0
+ || chan->qh_end.tv_usec != 0
+ ) {
+ chan->qh_start.tv_sec = 0;
+ chan->qh_start.tv_usec = 0;
+ chan->qh_end.tv_sec = 0;
+ chan->qh_end.tv_usec = 0;
+ WARN_ON(1);
+ }
+ }
+ } else {
+ max_dma_desc_num_dynamic = MAX_DMA_DESC_NUM_GENERIC;
+ }
+#endif
+
dev_vdbg(hsotg->dev, "%s(): qh=%p dma=%08lx len=%d\n", __func__, qh,
(unsigned long)chan->xfer_dma, chan->xfer_len);
@@ -791,13 +863,21 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
qtd->n_desc++;
n_desc++;
} while (chan->xfer_len > 0 &&
- n_desc != MAX_DMA_DESC_NUM_GENERIC);
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ n_desc != max_dma_desc_num_dynamic);
+#else
+ n_desc != MAX_DMA_DESC_NUM_GENERIC);
+#endif
dev_vdbg(hsotg->dev, "n_desc=%d\n", n_desc);
qtd->in_process = 1;
if (qh->ep_type == USB_ENDPOINT_XFER_CONTROL)
break;
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ if (n_desc == max_dma_desc_num_dynamic)
+#else
if (n_desc == MAX_DMA_DESC_NUM_GENERIC)
+#endif
break;
}
@@ -821,6 +901,9 @@ static void dwc2_init_non_isoc_dma_desc(struct dwc2_hsotg *hsotg,
DMA_TO_DEVICE);
}
chan->ntd = n_desc;
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ qh->max_dma_desc_num_lastime = n_desc;
+#endif
}
}
@@ -853,6 +936,22 @@ void dwc2_hcd_start_xfer_ddma(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
case USB_ENDPOINT_XFER_CONTROL:
case USB_ENDPOINT_XFER_BULK:
dwc2_init_non_isoc_dma_desc(hsotg, qh);
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ if (hsotg->core_params->dma_desc_enable
+ && chan->ep_type == USB_ENDPOINT_XFER_BULK
+ && chan->ep_is_in) {
+ if (chan->qh_start.tv_sec == 0
+ && chan->qh_start.tv_usec == 0
+ && chan->qh_end.tv_sec == 0
+ && chan->qh_end.tv_usec == 0) {
+ do_gettimeofday(&chan->qh_start);
+ } else {
+ chan->qh_start.tv_sec = 0;
+ chan->qh_start.tv_usec = 0;
+ WARN_ON(1);
+ }
+ }
+#endif
dwc2_hc_start_transfer_ddma(hsotg, chan);
break;
case USB_ENDPOINT_XFER_INT:
@@ -1303,6 +1402,32 @@ void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg *hsotg,
int continue_isoc_xfer = 0;
enum dwc2_transaction_type tr_type;
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST_DMA_DESC_NUM_DYNAMIC)
+ if (hsotg->core_params->dma_desc_enable
+ && chan->ep_type == USB_ENDPOINT_XFER_BULK
+ && chan->ep_is_in) {
+ if ((chan->qh_start.tv_sec != 0
+ || chan->qh_start.tv_usec != 0)
+ &&
+ (chan->qh_end.tv_sec == 0
+ && chan->qh_end.tv_usec == 0)) {
+ do_gettimeofday(&chan->qh_end);
+ qh->qh_dura.tv_sec
+ = chan->qh_end.tv_sec - chan->qh_start.tv_sec;
+ qh->qh_dura.tv_usec
+ = chan->qh_end.tv_usec - chan->qh_start.tv_usec;
+ chan->qh_start.tv_sec = 0;
+ chan->qh_start.tv_usec = 0;
+ chan->qh_end.tv_sec = 0;
+ chan->qh_end.tv_usec = 0;
+ } else {
+ qh->qh_dura.tv_sec = 0;
+ qh->qh_dura.tv_usec = 0;
+ WARN_ON(1);
+ }
+ }
+#endif
+
if (chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
dwc2_complete_isoc_xfer_ddma(hsotg, chan, halt_status);
diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 8066fa9a..e39210bd 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -488,7 +488,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
&short_read);
if (urb->actual_length + xfer_length > urb->length) {
- dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__);
+ dev_dbg(hsotg->dev, "%s(): trimming xfer length\n", __func__);
xfer_length = urb->length - urb->actual_length;
}
@@ -1921,6 +1921,18 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
qtd->error_count++;
dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb,
qtd, DWC2_HC_XFER_XACT_ERR);
+ /*
+ * We can get here after a completed transaction
+ * (urb->actual_length >= urb->length) which was not reported
+ * as completed. If that is the case, and we do not abort
+ * the transfer, a transfer of size 0 will be enqueued
+ * subsequently. If urb->actual_length is not DMA-aligned,
+ * the buffer will then point to an unaligned address, and
+ * the resulting behavior is undefined. Bail out in that
+ * situation.
+ */
+ if (qtd->urb->actual_length >= qtd->urb->length)
+ qtd->error_count = 3;
dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR);
}
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index 91058441..944c3ee3 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -53,6 +53,8 @@
#define GOTGCTL_HSTSETHNPEN (1 << 10)
#define GOTGCTL_HNPREQ (1 << 9)
#define GOTGCTL_HSTNEGSCS (1 << 8)
+#define GOTGCTL_VBVALIDOVVAL (1 << 3)
+#define GOTGCTL_VBVALIDOVEN (1 << 2)
#define GOTGCTL_SESREQ (1 << 1)
#define GOTGCTL_SESREQSCS (1 << 0)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 8e1728b3..40b556bf 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -46,14 +46,55 @@
#include <linux/phy/phy.h>
#include <linux/platform_data/s3c-hsotg.h>
#include <linux/reset.h>
-
+#include <linux/gpio.h>
#include <linux/usb/of.h>
+#include <mach/pmu.h>
+
#include "core.h"
#include "hcd.h"
#include "debug.h"
-static const char dwc2_driver_name[] = "dwc2";
+static const struct dwc2_core_params params_fh = {
+ .otg_cap = 0, /* HNP/SRP capable */
+ .otg_ver = 0, /* 1.3 */
+#ifdef CONFIG_USB_DWC2_DMA
+ .dma_enable = 1,
+#else
+ .dma_enable = 0,
+#endif
+#ifdef CONFIG_USB_DWC2_DMA_DESC
+ .dma_desc_enable = 1,
+#else
+ .dma_desc_enable = 0,
+#endif
+ .speed = 0, /* High Speed */
+ .enable_dynamic_fifo = 1,
+ .en_multiple_tx_fifo = 1,
+ .host_rx_fifo_size = 542, /* 542 DWORDs */
+ .host_nperio_tx_fifo_size = 256, /* 256 DWORDs */
+ .host_perio_tx_fifo_size = 512, /* 512 DWORDs */
+ .max_transfer_size = 65535,
+ .max_packet_count = 511,
+ .host_channels = 8,
+ .phy_type = 1, /* UTMI */
+#ifdef CONFIG_FPGA
+ .phy_utmi_width = 8, /* 8 bits */
+#else
+ .phy_utmi_width = 16, /* 16 bits */
+#endif
+ .phy_ulpi_ddr = 0, /* Single */
+ .phy_ulpi_ext_vbus = 0,
+ .i2c_enable = 0,
+ .ulpi_fs_ls = 0,
+ .host_support_fs_ls_low_power = 0,
+ .host_ls_low_power_phy_clk = 0, /* 48 MHz */
+ .ts_dline = 0,
+ .reload_ctl = 0,
+ .ahbcfg = GAHBCFG_HBSTLEN_INCR16 <<
+ GAHBCFG_HBSTLEN_SHIFT,
+ .uframe_sched = 0,
+};
static const struct dwc2_core_params params_hi6220 = {
.otg_cap = 2, /* No HNP/SRP capable */
@@ -214,6 +255,50 @@ static const struct dwc2_core_params params_amlogic = {
.hibernation = -1,
};
+/*usb*/
+static void fh_usb_utmi_rst(void)
+{
+ fh_pmu_usb_utmi_rst();
+}
+
+static void fh_usb_phy_rst(void)
+{
+ fh_pmu_usb_phy_rst();
+}
+
+static void fh_usb_resume(void)
+{
+ fh_pmu_usb_resume();
+}
+
+/*usb vbus power on*/
+static void fh_usb_pwr_on(struct dwc2_hsotg *hsotg)
+{
+ uint32_t pwren_gpio = 0;
+
+ pwren_gpio = usb_get_vbus_pwren_gpio(hsotg->dev);
+
+ if (pwren_gpio == 0xFFFFFFFF) {
+ dev_warn(hsotg->dev,
+ "Can't find usb vbus pwren gpio\n");
+ return;
+ }
+
+ if (hsotg->dr_mode == USB_DR_MODE_HOST) {
+ gpio_request(pwren_gpio, "usb_pwren");
+ gpio_direction_output(pwren_gpio, 1);
+ mdelay(1);
+ gpio_free(pwren_gpio);
+ }
+
+ if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
+ gpio_request(pwren_gpio, "usb_pwren");
+ gpio_direction_output(pwren_gpio, 0);
+ mdelay(1);
+ gpio_free(pwren_gpio);
+ }
+}
+
/*
* Check the dr_mode against the module configuration and hardware
* capabilities.
@@ -281,7 +366,6 @@ static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg)
static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
{
- struct platform_device *pdev = to_platform_device(hsotg->dev);
int ret;
ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
@@ -291,20 +375,24 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
if (hsotg->clk) {
ret = clk_prepare_enable(hsotg->clk);
- if (ret)
+ if (ret) {
+ dev_dbg(hsotg->dev, "usb clock enable failed and result usb driver probe ending!\n");
return ret;
+ }
}
- if (hsotg->uphy)
- ret = usb_phy_init(hsotg->uphy);
- else if (hsotg->plat && hsotg->plat->phy_init)
- ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
- else {
- ret = phy_power_on(hsotg->phy);
- if (ret == 0)
- ret = phy_init(hsotg->phy);
+ if (hsotg->clk2) {
+ ret = clk_prepare_enable(hsotg->clk2);
+ if (ret) {
+ dev_dbg(hsotg->dev, "usb clock2 enable failed and result usb driver probe ending!\n");
+ return ret;
+ }
}
+ fh_usb_phy_rst();
+ fh_usb_utmi_rst();
+ fh_usb_resume();
+
return ret;
}
@@ -326,24 +414,14 @@ int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
{
- struct platform_device *pdev = to_platform_device(hsotg->dev);
int ret = 0;
- if (hsotg->uphy)
- usb_phy_shutdown(hsotg->uphy);
- else if (hsotg->plat && hsotg->plat->phy_exit)
- ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
- else {
- ret = phy_exit(hsotg->phy);
- if (ret == 0)
- ret = phy_power_off(hsotg->phy);
- }
- if (ret)
- return ret;
-
if (hsotg->clk)
clk_disable_unprepare(hsotg->clk);
+ if (hsotg->clk2)
+ clk_disable_unprepare(hsotg->clk2);
+
ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
@@ -370,6 +448,7 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
{
int i, ret;
+#if 0
hsotg->reset = devm_reset_control_get_optional(hsotg->dev, "dwc2");
if (IS_ERR(hsotg->reset)) {
ret = PTR_ERR(hsotg->reset);
@@ -387,67 +466,23 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
if (hsotg->reset)
reset_control_deassert(hsotg->reset);
-
- /* Set default UTMI width */
- hsotg->phyif = GUSBCFG_PHYIF16;
-
- /*
- * Attempt to find a generic PHY, then look for an old style
- * USB PHY and then fall back to pdata
- */
- hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy");
- if (IS_ERR(hsotg->phy)) {
- ret = PTR_ERR(hsotg->phy);
- switch (ret) {
- case -ENODEV:
- case -ENOSYS:
- hsotg->phy = NULL;
- break;
- case -EPROBE_DEFER:
- return ret;
- default:
- dev_err(hsotg->dev, "error getting phy %d\n", ret);
- return ret;
- }
- }
-
- if (!hsotg->phy) {
- hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR(hsotg->uphy)) {
- ret = PTR_ERR(hsotg->uphy);
- switch (ret) {
- case -ENODEV:
- case -ENXIO:
- hsotg->uphy = NULL;
- break;
- case -EPROBE_DEFER:
- return ret;
- default:
- dev_err(hsotg->dev, "error getting usb phy %d\n",
- ret);
- return ret;
- }
- }
- }
+#endif
hsotg->plat = dev_get_platdata(hsotg->dev);
- if (hsotg->phy) {
- /*
- * If using the generic PHY framework, check if the PHY bus
- * width is 8-bit and set the phyif appropriately.
- */
- if (phy_get_bus_width(hsotg->phy) == 8)
- hsotg->phyif = GUSBCFG_PHYIF8;
- }
-
/* Clock */
- hsotg->clk = devm_clk_get(hsotg->dev, "otg");
+ hsotg->clk = clk_get(NULL, "usb_clk");
if (IS_ERR(hsotg->clk)) {
hsotg->clk = NULL;
dev_dbg(hsotg->dev, "cannot get otg clock\n");
}
+ hsotg->clk2 = clk_get(NULL, "usb_hclk");
+ if (IS_ERR(hsotg->clk2)) {
+ hsotg->clk2 = NULL;
+ dev_dbg(hsotg->dev, "cannot get otg clock2\n");
+ }
+
/* Regulators */
for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i];
@@ -488,6 +523,16 @@ static int dwc2_driver_remove(struct platform_device *dev)
if (hsotg->reset)
reset_control_assert(hsotg->reset);
+ if (hsotg->clk) {
+ clk_put(hsotg->clk);
+ hsotg->clk = NULL;
+ }
+
+ if (hsotg->clk2) {
+ clk_put(hsotg->clk2);
+ hsotg->clk2 = NULL;
+ }
+
return 0;
}
@@ -517,6 +562,7 @@ static const struct of_device_id dwc2_of_match_table[] = {
{ .compatible = "lantiq,arx100-usb", .data = &params_ltq },
{ .compatible = "lantiq,xrx200-usb", .data = &params_ltq },
{ .compatible = "snps,dwc2", .data = NULL },
+ { .compatible = "fh_usb", .data = &params_fh },
{ .compatible = "samsung,s3c6400-hsotg", .data = NULL},
{ .compatible = "amlogic,meson8b-usb", .data = &params_amlogic },
{ .compatible = "amlogic,meson-gxbb-usb", .data = &params_amlogic },
@@ -524,6 +570,8 @@ static const struct of_device_id dwc2_of_match_table[] = {
};
MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
+
+
/**
* dwc2_driver_probe() - Called when the DWC_otg core is bound to the DWC_otg
* driver
@@ -538,13 +586,18 @@ MODULE_DEVICE_TABLE(of, dwc2_of_match_table);
*/
static int dwc2_driver_probe(struct platform_device *dev)
{
+#ifdef CONFIG_USE_OF
const struct of_device_id *match;
+#else
+ int tbl_idx, tbl_size = ARRAY_SIZE(dwc2_of_match_table);
+#endif
const struct dwc2_core_params *params;
struct dwc2_core_params defparams;
struct dwc2_hsotg *hsotg;
struct resource *res;
int retval;
+#ifdef CONFIG_USE_OF
match = of_match_device(dwc2_of_match_table, &dev->dev);
if (match && match->data) {
params = match->data;
@@ -561,7 +614,28 @@ static int dwc2_driver_probe(struct platform_device *dev)
defparams.dma_desc_enable = 0;
defparams.dma_desc_fs_enable = 0;
}
+#else
+ for (tbl_idx = 0; tbl_idx < tbl_size; tbl_idx++)
+ if (strcmp(dev->name, dwc2_of_match_table[tbl_idx].compatible)
+ == 0)
+ break;
+
+ if (tbl_idx < tbl_size)
+ params = dwc2_of_match_table[tbl_idx].data;
+ else {
+ /* Default all params to autodetect */
+ dwc2_set_all_params(&defparams, -1);
+ params = &defparams;
+ /*
+ * Disable descriptor dma mode by default as the HW can support
+ * it, but does not support it for SPLIT transactions.
+ * Disable it for FS devices as well.
+ */
+ defparams.dma_desc_enable = 0;
+ defparams.dma_desc_fs_enable = 0;
+ }
+#endif
hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL);
if (!hsotg)
return -ENOMEM;
@@ -598,7 +672,11 @@ static int dwc2_driver_probe(struct platform_device *dev)
dwc2_set_all_params(hsotg->core_params, -1);
+#ifdef CONFIG_USE_OF
hsotg->irq = platform_get_irq(dev, 0);
+#else
+ hsotg->irq = irq_create_mapping(NULL, platform_get_irq(dev, 0));
+#endif
if (hsotg->irq < 0) {
dev_err(&dev->dev, "missing IRQ resource\n");
return hsotg->irq;
@@ -620,6 +698,8 @@ static int dwc2_driver_probe(struct platform_device *dev)
if (retval)
goto error;
+ fh_usb_pwr_on(hsotg);
+
/*
* Reset before dwc2_get_hwparams() then it could get power-on real
* reset value form registers.
@@ -705,7 +785,7 @@ static const struct dev_pm_ops dwc2_dev_pm_ops = {
static struct platform_driver dwc2_platform_driver = {
.driver = {
- .name = dwc2_driver_name,
+ .name = "fh_usb",
.of_match_table = dwc2_of_match_table,
.pm = &dwc2_dev_pm_ops,
},
@@ -714,7 +794,11 @@ static struct platform_driver dwc2_platform_driver = {
.shutdown = dwc2_driver_shutdown,
};
+#ifdef CONFIG_DEFERRED_INIICALLS_USB
+deferred_module_platform_driver(dwc2_platform_driver);
+#else
module_platform_driver(dwc2_platform_driver);
+#endif
MODULE_DESCRIPTION("DESIGNWARE HS OTG Platform Glue");
MODULE_AUTHOR("Matthijs Kooijman <matthijs@stdin.nl>");
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index f3ee80ec..a6b936c0 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -481,4 +481,24 @@ source "drivers/usb/gadget/legacy/Kconfig"
endchoice
+config USB_G_WEBCAM_PATCH
+ bool "UVC fix upgrade"
+ depends on USB_G_WEBCAM
+ default y
+
+config UVC_ACM_COM
+ bool "enable acm vcom driver(serial)"
+ depends on USB_G_WEBCAM
+ default n
+
+config UVC_INS_UAC
+ bool "enable uac driver"
+ depends on USB_G_WEBCAM
+ default y
+
+config ENABLE_SPEAKER_DESC
+ bool "enable uac speaker driver"
+ depends on USB_G_WEBCAM && UVC_INS_UAC
+ default y
+
endif # USB_GADGET
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index cb8c225e..e99e712b 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -36,7 +36,7 @@ usb_f_uac1-y := f_uac1.o u_uac1.o
obj-$(CONFIG_USB_F_UAC1) += usb_f_uac1.o
usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
-usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o
+usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o uvc_format.o
obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o
usb_f_midi-y := f_midi.o
obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o
diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c
index 5e3828d9..44b6df74 100644
--- a/drivers/usb/gadget/function/f_acm.c
+++ b/drivers/usb/gadget/function/f_acm.c
@@ -491,7 +491,7 @@ static void acm_disable(struct usb_function *f)
* about the only notification we issue: SerialState change.
*/
static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
- void *data, unsigned length)
+ void *data, unsigned int length)
{
struct usb_ep *ep = acm->notify;
struct usb_request *req;
@@ -819,5 +819,7 @@ static struct usb_function_instance *acm_alloc_instance(void)
&acm_func_type);
return &opts->func_inst;
}
+
DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c
index e7009383..73d2ef45 100644
--- a/drivers/usb/gadget/function/f_loopback.c
+++ b/drivers/usb/gadget/function/f_loopback.c
@@ -302,7 +302,8 @@ static void disable_loopback(struct f_loopback *loop)
struct usb_composite_dev *cdev;
cdev = loop->function.config->cdev;
- disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
+ disable_endpoints(cdev, loop->in_ep, loop->out_ep,
+ NULL, NULL, NULL, NULL);
VDBG(cdev, "%s disabled\n", loop->function.name);
}
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index 8784fa12..03b355b0 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -40,18 +40,24 @@ struct f_sourcesink {
struct usb_ep *in_ep;
struct usb_ep *out_ep;
+ struct usb_ep *int_in_ep;
+ struct usb_ep *int_out_ep;
struct usb_ep *iso_in_ep;
struct usb_ep *iso_out_ep;
int cur_alt;
- unsigned pattern;
- unsigned isoc_interval;
- unsigned isoc_maxpacket;
- unsigned isoc_mult;
- unsigned isoc_maxburst;
- unsigned buflen;
- unsigned bulk_qlen;
- unsigned iso_qlen;
+ unsigned int pattern;
+ unsigned int int_interval;
+ unsigned int int_maxpacket;
+ unsigned int int_maxburst;
+ unsigned int isoc_interval;
+ unsigned int isoc_maxpacket;
+ unsigned int isoc_mult;
+ unsigned int isoc_maxburst;
+ unsigned int buflen;
+ unsigned int bulk_qlen;
+ unsigned int int_qlen;
+ unsigned int iso_qlen;
};
static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@@ -76,7 +82,7 @@ static struct usb_interface_descriptor source_sink_intf_alt1 = {
.bDescriptorType = USB_DT_INTERFACE,
.bAlternateSetting = 1,
- .bNumEndpoints = 4,
+ .bNumEndpoints = 6,
.bInterfaceClass = USB_CLASS_VENDOR_SPEC,
/* .iInterface = DYNAMIC */
};
@@ -99,6 +105,26 @@ static struct usb_endpoint_descriptor fs_sink_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
+static struct usb_endpoint_descriptor fs_int_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(64),
+ .bInterval = 4,
+};
+
+static struct usb_endpoint_descriptor fs_int_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(64),
+ .bInterval = 4,
+};
+
static struct usb_endpoint_descriptor fs_iso_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -127,6 +153,8 @@ static struct usb_descriptor_header *fs_source_sink_descs[] = {
#define FS_ALT_IFC_1_OFFSET 3
(struct usb_descriptor_header *) &fs_sink_desc,
(struct usb_descriptor_header *) &fs_source_desc,
+ (struct usb_descriptor_header *) &fs_int_sink_desc,
+ (struct usb_descriptor_header *) &fs_int_source_desc,
(struct usb_descriptor_header *) &fs_iso_sink_desc,
(struct usb_descriptor_header *) &fs_iso_source_desc,
NULL,
@@ -150,6 +178,24 @@ static struct usb_endpoint_descriptor hs_sink_desc = {
.wMaxPacketSize = cpu_to_le16(512),
};
+static struct usb_endpoint_descriptor hs_int_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(1024),
+ .bInterval = 4,
+};
+
+static struct usb_endpoint_descriptor hs_int_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(1024),
+ .bInterval = 4,
+};
+
static struct usb_endpoint_descriptor hs_iso_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -176,6 +222,8 @@ static struct usb_descriptor_header *hs_source_sink_descs[] = {
#define HS_ALT_IFC_1_OFFSET 3
(struct usb_descriptor_header *) &hs_source_desc,
(struct usb_descriptor_header *) &hs_sink_desc,
+ (struct usb_descriptor_header *) &hs_int_source_desc,
+ (struct usb_descriptor_header *) &hs_int_sink_desc,
(struct usb_descriptor_header *) &hs_iso_source_desc,
(struct usb_descriptor_header *) &hs_iso_sink_desc,
NULL,
@@ -307,10 +355,15 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out,
+ struct usb_ep *int_in, struct usb_ep *int_out,
struct usb_ep *iso_in, struct usb_ep *iso_out)
{
disable_ep(cdev, in);
disable_ep(cdev, out);
+ if (int_in)
+ disable_ep(cdev, int_in);
+ if (int_out)
+ disable_ep(cdev, int_out);
if (iso_in)
disable_ep(cdev, iso_in);
if (iso_out)
@@ -345,6 +398,43 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
if (!ss->out_ep)
goto autoconf_fail;
+ /* sanity check the int module parameters */
+ if (ss->int_interval < 1)
+ ss->int_interval = 1;
+ if (ss->int_interval > 16)
+ ss->int_interval = 16;
+ if (ss->int_maxburst > 15)
+ ss->int_maxburst = 15;
+
+ /* fill in the FS int descriptors from the module parameters */
+ fs_int_source_desc.wMaxPacketSize = ss->int_maxpacket > 64 ?
+ 64 : ss->int_maxpacket;
+ fs_int_source_desc.bInterval = ss->int_interval;
+ fs_int_sink_desc.wMaxPacketSize = ss->int_maxpacket > 64 ?
+ 64 : ss->int_maxpacket;
+ fs_int_sink_desc.bInterval = ss->int_interval;
+
+
+ /* allocate int endpoints */
+ ss->int_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_source_desc);
+ if (!ss->int_in_ep)
+ goto no_int;
+
+ ss->int_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_int_sink_desc);
+ if (!ss->int_out_ep) {
+ usb_ep_autoconfig_release(ss->int_in_ep);
+ ss->int_in_ep = NULL;
+no_int:
+ /*
+ * We still want to work even if the UDC doesn't have int
+ * endpoints, so null out the alt interface that contains
+ * them and continue.
+ */
+ fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL;
+ hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL;
+ ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
+ }
+
/* sanity check the isoc module parameters */
if (ss->isoc_interval < 1)
ss->isoc_interval = 1;
@@ -383,6 +473,8 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
}
+ if (ss->int_maxpacket > 1024)
+ ss->int_maxpacket = 1024;
if (ss->isoc_maxpacket > 1024)
ss->isoc_maxpacket = 1024;
@@ -390,6 +482,19 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
+ /*
+ * Fill in the HS int descriptors from the module parameters.
+ * We assume that the user knows what they are doing and won't
+ * give parameters that their UDC doesn't support.
+ */
+ hs_int_source_desc.wMaxPacketSize = ss->int_maxpacket;
+ hs_int_source_desc.bInterval = ss->int_interval;
+ hs_int_source_desc.bEndpointAddress = fs_int_source_desc.bEndpointAddress;
+
+ hs_int_sink_desc.wMaxPacketSize = ss->int_maxpacket;
+ hs_int_sink_desc.bInterval = ss->int_interval;
+ hs_int_sink_desc.bEndpointAddress = fs_int_sink_desc.bEndpointAddress;
+
/*
* Fill in the HS isoc descriptors from the module parameters.
* We assume that the user knows what they are doing and won't
@@ -578,7 +683,7 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
}
static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
- bool is_iso, int speed)
+ bool is_int, bool is_iso, int speed)
{
struct usb_ep *ep;
struct usb_request *req;
@@ -601,6 +706,23 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
}
ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
qlen = ss->iso_qlen;
+ } else if (is_int) {
+ switch (speed) {
+ case USB_SPEED_SUPER:
+ size = ss->int_maxpacket *
+ (ss->int_maxburst + 1);
+ break;
+ case USB_SPEED_HIGH:
+ size = ss->int_maxpacket > 1024 ?
+ 1024 : ss->int_maxpacket;
+ break;
+ default:
+ size = ss->int_maxpacket > 64 ?
+ 64 : ss->int_maxpacket;
+ break;
+ }
+ ep = is_in ? ss->int_in_ep : ss->int_out_ep;
+ qlen = ss->int_qlen;
} else {
ep = is_in ? ss->in_ep : ss->out_ep;
qlen = ss->bulk_qlen;
@@ -639,8 +761,8 @@ static void disable_source_sink(struct f_sourcesink *ss)
struct usb_composite_dev *cdev;
cdev = ss->function.config->cdev;
- disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep,
- ss->iso_out_ep);
+ disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->int_in_ep,
+ ss->int_out_ep, ss->iso_in_ep, ss->iso_out_ep);
VDBG(cdev, "%s disabled\n", ss->function.name);
}
@@ -662,7 +784,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
return result;
ep->driver_data = ss;
- result = source_sink_start_ep(ss, true, false, speed);
+ result = source_sink_start_ep(ss, true, false, false, speed);
if (result < 0) {
fail:
ep = ss->in_ep;
@@ -680,7 +802,7 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
goto fail;
ep->driver_data = ss;
- result = source_sink_start_ep(ss, false, false, speed);
+ result = source_sink_start_ep(ss, false, false, false, speed);
if (result < 0) {
fail2:
ep = ss->out_ep;
@@ -690,9 +812,8 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
if (alt == 0)
goto out;
-
- /* one iso endpoint writes (sources) zeroes IN (to the host) */
- ep = ss->iso_in_ep;
+ /* one int endpoint writes (sources) zeroes IN (to the host) */
+ ep = ss->int_in_ep;
if (ep) {
result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
if (result)
@@ -702,18 +823,18 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
goto fail2;
ep->driver_data = ss;
- result = source_sink_start_ep(ss, true, true, speed);
+ result = source_sink_start_ep(ss, true, true, false, speed);
if (result < 0) {
fail3:
- ep = ss->iso_in_ep;
+ ep = ss->int_in_ep;
if (ep)
usb_ep_disable(ep);
goto fail2;
}
}
- /* one iso endpoint reads (sinks) anything OUT (from the host) */
- ep = ss->iso_out_ep;
+ /* one int endpoint reads (sinks) anything OUT (from the host) */
+ ep = ss->int_out_ep;
if (ep) {
result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
if (result)
@@ -723,12 +844,54 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
goto fail3;
ep->driver_data = ss;
- result = source_sink_start_ep(ss, false, true, speed);
+ result = source_sink_start_ep(ss, false, true, false, speed);
if (result < 0) {
+fail4:
+ ep = ss->int_out_ep;
usb_ep_disable(ep);
goto fail3;
}
}
+
+ /* one iso endpoint writes (sources) zeroes IN (to the host) */
+ ep = ss->iso_in_ep;
+ if (ep) {
+ result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+ if (result)
+ goto fail4;
+ result = usb_ep_enable(ep);
+ if (result < 0)
+ goto fail4;
+ ep->driver_data = ss;
+
+ result = source_sink_start_ep(ss, true, false, true, speed);
+ if (result < 0) {
+fail5:
+ ep = ss->int_in_ep;
+ if (ep)
+ usb_ep_disable(ep);
+ goto fail4;
+ }
+ }
+
+ /* one iso endpoint reads (sinks) anything OUT (from the host) */
+ ep = ss->iso_out_ep;
+ if (ep) {
+ result = config_ep_by_speed(cdev->gadget, &(ss->function), ep);
+ if (result)
+ goto fail5;
+ result = usb_ep_enable(ep);
+ if (result < 0)
+ goto fail5;
+ ep->driver_data = ss;
+
+ result = source_sink_start_ep(ss, false, false, true, speed);
+ if (result < 0) {
+ usb_ep_disable(ep);
+ goto fail5;
+ }
+ }
+
out:
ss->cur_alt = alt;
@@ -859,6 +1022,11 @@ static struct usb_function *source_sink_alloc_func(
ss->bulk_qlen = ss_opts->bulk_qlen;
ss->iso_qlen = ss_opts->iso_qlen;
+ ss->int_interval = ss_opts->int_interval;
+ ss->int_maxpacket = ss_opts->int_maxpacket;
+ ss->int_maxburst = ss_opts->int_maxburst;
+ ss->int_qlen = ss_opts->int_qlen;
+
ss->function.name = "source/sink";
ss->function.bind = sourcesink_bind;
ss->function.set_alt = sourcesink_set_alt;
@@ -1258,6 +1426,9 @@ static struct usb_function_instance *source_sink_alloc_inst(void)
ss_opts->bulk_buflen = GZERO_BULK_BUFLEN;
ss_opts->bulk_qlen = GZERO_SS_BULK_QLEN;
ss_opts->iso_qlen = GZERO_SS_ISO_QLEN;
+ ss_opts->int_interval = 4;//GZERO_ISOC_INTERVAL;
+ ss_opts->int_maxpacket = 1024;//GZERO_ISOC_MAXPACKET;
+ ss_opts->int_qlen = 1;//GZERO_SS_ISO_QLEN;
config_group_init_type_name(&ss_opts->func_inst.group, "",
&ss_func_type);
diff --git a/drivers/usb/gadget/function/f_uac.c b/drivers/usb/gadget/function/f_uac.c
new file mode 100644
index 00000000..bc4d7627
--- /dev/null
+++ b/drivers/usb/gadget/function/f_uac.c
@@ -0,0 +1,1219 @@
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/video.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+
+#include <linux/usb/audio.h>
+#include "f_uac.h"
+
+static void f_audio_complete(struct usb_ep *ep, struct usb_request *req);
+
+#define UAC_ERR(msg...) printk(KERN_EMERG "UAC, " msg)
+#define UAC_DBG(msg...) printk(KERN_INFO "UAC, " msg)
+#define UAC_INFO(msg...)
+
+
+
+#define UAC_STR_ASSOCIATION_IDX 0
+#define UAC_STR_CONTROL_IDX 1
+#define UAC_STR_STREAMING_IDX 2
+
+
+static struct usb_string uac_en_us_strings[] = {
+ [UAC_STR_ASSOCIATION_IDX].s = "Fullhan Audio",
+ [UAC_STR_CONTROL_IDX].s = "Audio Control",
+ [UAC_STR_STREAMING_IDX].s = "Audio Streaming",
+ { }
+};
+
+static struct usb_gadget_strings uac_stringtab = {
+ .language = 0x0409, /* en-us */
+ .strings = uac_en_us_strings,
+};
+
+static struct usb_gadget_strings *uac_function_strings[] = {
+ &uac_stringtab,
+ NULL,
+};
+
+
+
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+
+#define UAC_IF_COUNT 3
+#define UAC_COLLECTION_NUM 2
+#define AC_HEADER_TOTAL_LENGTH 0x44
+
+#else
+
+#define UAC_IF_COUNT 2
+#define UAC_COLLECTION_NUM 1
+#define AC_HEADER_TOTAL_LENGTH 0x26
+
+
+#endif
+
+
+static struct usb_interface_assoc_descriptor audio_iad_desc = {
+ .bLength = 0x08,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 2,
+ .bInterfaceCount = UAC_IF_COUNT,
+ .bFunctionClass = USB_CLASS_AUDIO,
+ .bFunctionSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+ .bFunctionProtocol = 0x00,
+ .iFunction = 0,
+};
+
+
+static struct usb_interface_descriptor ac_intf_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 2,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+ .bInterfaceProtocol = 0x00,
+ .iInterface = 0,
+};
+
+
+#define AC_SIZE_NUM 2
+
+DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
+
+/* B.3.2 Class-Specific AC Interface Descriptor */
+static struct uac1_ac_header_descriptor_2 ac_header_desc = {
+ .bLength = UAC_DT_AC_HEADER_SIZE(UAC_COLLECTION_NUM),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_HEADER,
+ .bcdADC = __constant_cpu_to_le16(0x0100),
+ .wTotalLength = __constant_cpu_to_le16(AC_HEADER_TOTAL_LENGTH),
+ .bInCollection = UAC_COLLECTION_NUM,
+ .baInterfaceNr[0] = 3,
+ .baInterfaceNr[1] = 4,
+};
+
+
+
+#define INPUT_TERMINAL_ID 1
+#define AUDIO_CHN_NUM 1
+static struct uac_input_terminal_descriptor audio_mic_it_desc = {
+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_INPUT_TERMINAL,
+ .bTerminalID = INPUT_TERMINAL_ID,
+ .wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE,
+ .bAssocTerminal = 0,
+ .bNrChannels = 1,
+ .wChannelConfig = 0x0,
+};
+
+
+#define OUTPUT_TERMINAL_ID 3
+#define FEATURE_UNIT_ID 5
+
+static struct uac1_output_terminal_descriptor audio_mic_ot_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = OUTPUT_TERMINAL_ID,
+ .wTerminalType = UAC_TERMINAL_STREAMING,
+ .bAssocTerminal = 0,
+ .bSourceID = FEATURE_UNIT_ID,
+ .iTerminal = 0,
+};
+
+
+DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0);
+
+
+static struct uac_feature_unit_descriptor_0 audio_mic_fu_desc = {
+ .bLength = 0x08,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FEATURE_UNIT,
+ .bUnitID = FEATURE_UNIT_ID,
+ .bSourceID = INPUT_TERMINAL_ID,
+ .bControlSize = 1,
+ .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME),
+};
+
+
+#define SPEAKER_IT_ID 4
+#define SPEAKER_FU_ID 6
+#define SPEAKER_OT_ID 8
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+static struct uac_input_terminal_descriptor audio_spk_it_desc = {
+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_INPUT_TERMINAL,
+ .bTerminalID = SPEAKER_IT_ID,
+ .wTerminalType = UAC_TERMINAL_STREAMING,
+ .bAssocTerminal = 0,
+ .bNrChannels = 1,
+ .wChannelConfig = 0x0,
+};
+
+
+
+static struct uac_feature_unit_descriptor_0 audio_spk_fu_desc = {
+ .bLength = 0x08,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FEATURE_UNIT,
+ .bUnitID = SPEAKER_FU_ID,
+ .bSourceID = SPEAKER_IT_ID,
+ .bControlSize = 1,
+ .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME),
+};
+
+static struct uac1_output_terminal_descriptor audio_spk_ot_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = SPEAKER_OT_ID,
+ .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER,
+ .bAssocTerminal = 0,
+ .bSourceID = SPEAKER_FU_ID,
+ .iTerminal = 0,
+};
+
+#endif
+
+
+/* Standard AS Interface Descriptor */
+static struct usb_interface_descriptor as_mic_if_alt_0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 3,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+static struct usb_interface_descriptor as_mic_if_alt_1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 3,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+
+/* B.4.2 Class-Specific AS Interface Descriptor */
+static struct uac1_as_header_descriptor as_mic_header_desc = {
+ .bLength = UAC_DT_AS_HEADER_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_AS_GENERAL,
+ .bTerminalLink = OUTPUT_TERMINAL_ID,
+ .bDelay = 0x01,
+ .wFormatTag = UAC_FORMAT_TYPE_I_PCM,
+};
+
+
+#define SAMPLE_FREQ (8000)
+#define SAMPLE_FREQ_16K (16000)
+DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(2);
+
+static struct uac_format_type_i_discrete_descriptor_2 as_mic_type_i_desc = {
+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(2),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FORMAT_TYPE,
+ .bFormatType = UAC_FORMAT_TYPE_I,
+ .bNrChannels = AUDIO_CHN_NUM,
+ .bSubframeSize = 2,
+ .bBitResolution = 16,
+ .bSamFreqType = 2,
+ .tSamFreq[0][0] = (SAMPLE_FREQ & 0xff),
+ .tSamFreq[0][1] = (SAMPLE_FREQ >> 8) & 0xff,
+ .tSamFreq[0][2] = 0,
+ .tSamFreq[1][0] = (SAMPLE_FREQ_16K & 0xff),
+ .tSamFreq[1][1] = (SAMPLE_FREQ_16K >> 8) & 0xff,
+ .tSamFreq[1][2] = 0,
+};
+
+
+static struct usb_endpoint_descriptor audio_mic_streaming_ep = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN|5,
+ .bmAttributes = 0x05,/*USB_ENDPOINT_XFER_ISOC,*/
+ .wMaxPacketSize = cpu_to_le16(68),
+ .bInterval = 4,
+};
+
+
+/* Class-specific AS ISO OUT Endpoint Descriptor */
+static struct uac_iso_endpoint_descriptor as_mic_iso_out_desc = {
+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
+ .bDescriptorType = USB_DT_CS_ENDPOINT,
+ .bDescriptorSubtype = UAC_EP_GENERAL,
+ .bmAttributes = 1,
+ .bLockDelayUnits = 0,
+ .wLockDelay = 0,
+};
+
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+/*speaker*/
+/* Standard AS Interface Descriptor */
+static struct usb_interface_descriptor as_spk_if_alt_0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 4,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+static struct usb_interface_descriptor as_spk_if_alt_1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 4,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+
+/* B.4.2 Class-Specific AS Interface Descriptor */
+static struct uac1_as_header_descriptor as_spk_header_desc = {
+ .bLength = UAC_DT_AS_HEADER_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_AS_GENERAL,
+ .bTerminalLink = SPEAKER_IT_ID,
+ .bDelay = 0x01,
+ .wFormatTag = UAC_FORMAT_TYPE_I_PCM,
+};
+
+
+static struct uac_format_type_i_discrete_descriptor_2 as_spk_type_i_desc = {
+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(2),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FORMAT_TYPE,
+ .bFormatType = UAC_FORMAT_TYPE_I,
+ .bNrChannels = AUDIO_CHN_NUM,
+ .bSubframeSize = 2,
+ .bBitResolution = 16,
+ .bSamFreqType = 2,
+ .tSamFreq[0][0] = (SAMPLE_FREQ & 0xff),
+ .tSamFreq[0][1] = (SAMPLE_FREQ >> 8) & 0xff,
+ .tSamFreq[0][2] = 0,
+ .tSamFreq[1][0] = (SAMPLE_FREQ_16K & 0xff),
+ .tSamFreq[1][1] = (SAMPLE_FREQ_16K >> 8) & 0xff,
+ .tSamFreq[1][2] = 0,
+
+};
+
+
+static struct usb_endpoint_descriptor audio_spk_streaming_ep = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT|6,
+ .bmAttributes = 0x05,/*USB_ENDPOINT_XFER_ISOC,*/
+ .wMaxPacketSize = cpu_to_le16(68),
+ .bInterval = 4,
+};
+
+
+/* Class-specific AS ISO OUT Endpoint Descriptor */
+static struct uac_iso_endpoint_descriptor as_spk_iso_out_desc = {
+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
+ .bDescriptorType = USB_DT_CS_ENDPOINT,
+ .bDescriptorSubtype = UAC_EP_GENERAL,
+ .bmAttributes = 0,
+ .bLockDelayUnits = 0,
+ .wLockDelay = 0,
+};
+
+#endif
+
+
+
+static struct usb_descriptor_header *f_audio_descs[] = {
+ (struct usb_descriptor_header *)&audio_iad_desc,
+ (struct usb_descriptor_header *)&ac_intf_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&audio_mic_it_desc,
+ (struct usb_descriptor_header *)&audio_mic_ot_desc,
+ (struct usb_descriptor_header *)&audio_mic_fu_desc,
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ (struct usb_descriptor_header *)&audio_spk_it_desc,
+ (struct usb_descriptor_header *)&audio_spk_ot_desc,
+ (struct usb_descriptor_header *)&audio_spk_fu_desc,
+#endif
+
+
+ (struct usb_descriptor_header *)&as_mic_if_alt_0_desc,
+ (struct usb_descriptor_header *)&as_mic_if_alt_1_desc,
+ (struct usb_descriptor_header *)&as_mic_header_desc,
+ (struct usb_descriptor_header *)&as_mic_type_i_desc,
+ (struct usb_descriptor_header *)&audio_mic_streaming_ep,
+ (struct usb_descriptor_header *)&as_mic_iso_out_desc,
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ (struct usb_descriptor_header *)&as_spk_if_alt_0_desc,
+ (struct usb_descriptor_header *)&as_spk_if_alt_1_desc,
+ (struct usb_descriptor_header *)&as_spk_header_desc,
+ (struct usb_descriptor_header *)&as_spk_type_i_desc,
+ (struct usb_descriptor_header *)&audio_spk_streaming_ep,
+ (struct usb_descriptor_header *)&as_spk_iso_out_desc,
+#endif
+ NULL,
+};
+
+
+
+
+#define UAC_STREAM_OFF 0
+#define UAC_STREAM_ON 1
+#define AUDIO_REQ_NUM 32
+#define AUDIO_REC_NUM 256
+
+struct uac_audio {
+ struct usb_function *func;
+ struct usb_ep *ep;
+ struct usb_ep *out_ep;
+ struct usb_request *req[AUDIO_REQ_NUM];
+ void *req_buf[AUDIO_REQ_NUM];
+ int req_valid[AUDIO_REQ_NUM];
+ int req_buf_size;
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ struct f_audio_buf *copy_buf;
+ struct usb_request *out_req[AUDIO_REC_NUM];
+ void *out_req_buf[AUDIO_REC_NUM];
+ int req_speaker_buf_size;
+ int audio_buf_size;
+ int spk_sample_rate;
+ struct list_head play_queue;
+ struct work_struct playback_work;
+ spinlock_t lock;
+#endif
+ int ac_connected;
+ int stream_sta[3];
+ int ac_intf;
+ int as_mic_intf;
+ int as_spk_intf;
+
+ int mute_set;
+ int spkmute_set;
+ int vol_set;
+ int spkvol_set;
+ int sample_rate_set;
+ int set_cmd;
+ int set_id;
+
+};
+
+
+static struct uac_audio *g_audio;
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+static struct f_audio_buf *f_audio_buffer_alloc(int buf_size)
+{
+ struct f_audio_buf *copy_buf;
+
+ copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC);
+ if (copy_buf == NULL)
+ return NULL;
+
+ copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC);
+ if (copy_buf->buf == NULL) {
+ kfree(copy_buf);
+ return NULL;
+ }
+
+ return copy_buf;
+}
+#endif
+
+static int uac_is_stream_on(int id)
+{
+ return (g_audio->stream_sta[id] == UAC_STREAM_ON);
+}
+
+static int uac_audio_enable(int enable, int id)
+{
+ unsigned int i, ret = 0;
+
+ if (id == 1)
+ uac_stream(enable);
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ else
+ uac_stream_spk(enable);
+#endif
+ if (!enable) {
+ if (uac_is_stream_on(id)) {
+ if (id == 1) {
+ for (i = 0; i < AUDIO_REQ_NUM; ++i)
+ usb_ep_dequeue(g_audio->ep, g_audio->req[i]);
+ usb_ep_disable(g_audio->ep);
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ } else if (id == 2) {
+ for (i = 0; i < AUDIO_REC_NUM; ++i)
+ usb_ep_dequeue(g_audio->out_ep, g_audio->out_req[i]);
+ usb_ep_disable(g_audio->out_ep);
+#endif
+ }
+ g_audio->stream_sta[id] = UAC_STREAM_OFF;
+ UAC_INFO("STREAM %s OFF\n", id == 1 ? "mic" : "speaker");
+ }
+ return 0;
+ }
+
+ if (id == 1)
+ {
+ ret = config_ep_by_speed(g_audio->func->config->cdev->gadget,
+ g_audio->func, g_audio->ep);
+ if (ret)
+ return ret;
+ usb_ep_enable(g_audio->ep);
+ }
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ if (id == 2)
+ {
+ ret = config_ep_by_speed(g_audio->func->config->cdev->gadget,
+ g_audio->func, g_audio->out_ep);
+ if (ret)
+ return ret;
+ usb_ep_enable(g_audio->out_ep);
+ }
+#endif
+
+ g_audio->stream_sta[id] = UAC_STREAM_ON;
+ UAC_INFO("STREAM %s ON\n", id == 1 ? "mic" : "speaker");
+ return 0;
+}
+
+
+void uac_begin_transfer_data(void)
+{
+ int i, err;
+ struct usb_request *req;
+
+ for (i = 0; i < AUDIO_REQ_NUM; i++) {
+ req = g_audio->req[i];
+ req->buf = g_audio->req_buf[i];
+ req->dma = (~(dma_addr_t)0);
+
+ g_audio->req_valid[i] = 0;
+ memset(req->buf, 0, g_audio->req_buf_size);
+ req->length = 0;
+ req->context = (void *)i;
+ req->complete = f_audio_complete;
+#if 1
+ err = usb_ep_queue(g_audio->ep, req, GFP_ATOMIC);
+ if (err)
+ UAC_ERR("transfer_data usb_ep_queue error, %s req: %d\n", g_audio->ep->name, err);
+#endif
+ }
+
+ wake_up_app();
+ UAC_INFO("sendMsg audio!\n");
+}
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+
+static void f_audio_buffer_free(struct f_audio_buf *audio_buf)
+{
+ kfree(audio_buf->buf);
+ kfree(audio_buf);
+}
+
+static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct uac_audio *audio = req->context;
+ struct f_audio_buf *copy_buf = audio->copy_buf;
+ int audio_buf_size;
+ int err;
+
+ audio_buf_size = audio->audio_buf_size;
+
+ if (!copy_buf)
+ return -EINVAL;
+
+ if (req->actual > 64) {
+ pr_err("copy_buf->actual %d req->actual %d\n",
+ copy_buf->actual, req->actual);
+ return -EINVAL;
+ }
+ if (req->actual == 32)
+ audio->spk_sample_rate = 16000;
+ else if (req->actual == 16)
+ audio->spk_sample_rate = 8000;
+ /* Copy buffer is full, add it to the play_queue */
+ if (audio_buf_size - copy_buf->actual < req->actual) {
+ list_add_tail(&copy_buf->list, &audio->play_queue);
+ wake_up_app_spk();
+ copy_buf = f_audio_buffer_alloc(audio_buf_size);
+ if (copy_buf == NULL) {
+ pr_err("%s--%d f_audio_buffer_alloc failed~\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ }
+
+ memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);
+ copy_buf->actual += req->actual;
+ audio->copy_buf = copy_buf;
+ err = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (err)
+ printk("%s queue req: %d\n", ep->name, err);
+
+ return 0;
+
+}
+
+int audio_recv_data(struct f_audio_buf *args)
+{
+ int ret;
+ struct f_audio_buf *play_buf;
+ struct f_audio_buf usr_buf;
+
+ ret = copy_from_user(&usr_buf, args, sizeof(struct f_audio_buf));
+
+ spin_lock_irq(&g_audio->lock);
+ if (list_empty(&g_audio->play_queue)) {
+ printk(KERN_EMERG "%s--%d play_queue is null\n", __func__, __LINE__);
+ spin_unlock_irq(&g_audio->lock);
+ return -1;
+ }
+ play_buf = list_first_entry(&g_audio->play_queue,
+ struct f_audio_buf, list);
+ list_del(&play_buf->list);
+ if (play_buf->buf && usr_buf.buf) {
+ ret = copy_to_user(usr_buf.buf, play_buf->buf, play_buf->actual);
+ put_user(play_buf->actual, (unsigned int __user *)&(args->actual));
+ }
+ spin_unlock_irq(&g_audio->lock);
+ f_audio_buffer_free(play_buf);
+ return 0;
+}
+
+#endif
+
+static void uac_event_proc(struct usb_ep *ep, struct usb_request *req)
+{
+ int a;
+ int sample;
+ unsigned char *pData = NULL;
+
+ if (ep != g_audio->ep && ep != g_audio->out_ep) {
+ if (!g_audio->set_cmd)
+ return;
+ pData = req->buf;
+ switch (g_audio->set_cmd) {
+ case UAC_FU_MUTE:
+ if (g_audio->set_id == FEATURE_UNIT_ID) {
+ g_audio->mute_set = pData[0];
+ uac_mic_FU();
+ }
+ else if (g_audio->set_id == SPEAKER_FU_ID) {
+ g_audio->spkmute_set = pData[0];
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ uac_spk_FU();
+#endif
+ }
+ break;
+ case UAC_FU_VOLUME:
+ if (g_audio->set_id == FEATURE_UNIT_ID) {
+ g_audio->vol_set = (pData[0] | pData[1] << 8)*100/UAC_MIC_MAX_GAIN;
+ if (g_audio->mute_set)
+ break;
+ uac_mic_FU();
+ }
+ else if (g_audio->set_id == SPEAKER_FU_ID) {
+ g_audio->spkvol_set = pData[0] | pData[1] << 8;
+ if (g_audio->spkmute_set)
+ break;
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ uac_spk_FU();
+#endif
+ }
+ break;
+ default:
+ if (g_audio->set_cmd == audio_mic_streaming_ep.bEndpointAddress) {
+ sample = (pData[0]) | (pData[1]<<8) | (pData[2]<<16);
+ if (sample != g_audio->sample_rate_set) {
+ g_audio->sample_rate_set = sample;
+ uac_stream(1);
+ }
+ }
+ break;
+ }
+ g_audio->set_cmd = 0;
+ return;
+ }
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ else if (ep == g_audio->out_ep)
+ f_audio_out_ep_complete(ep, req);
+#endif
+ else {
+ a = (int)req->context;
+ g_audio->req_valid[a] = 1;
+ wake_up_app();
+ }
+}
+
+static void f_audio_complete(struct usb_ep *ep, struct usb_request *req)
+{
+
+ switch (req->status) {
+ case 0:
+ uac_event_proc(ep, req);
+ break;
+
+ case -ESHUTDOWN:
+ UAC_INFO("f_audio_complete ESHUTDOWN.\n");
+ goto requeue;
+
+ default:
+ /* UAC_INFO("request completed with status %d.\n", req->status); */
+ goto requeue;
+ }
+
+requeue:
+ return;
+}
+
+int audio_mic_simple_rate(void)
+{
+ return g_audio->sample_rate_set;
+}
+
+int audio_mic_volume(void)
+{
+ return g_audio->vol_set;
+}
+
+int audio_mic_mute(void)
+{
+ return g_audio->mute_set;
+}
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+int audio_spk_simple_rate(void)
+{
+ return g_audio->spk_sample_rate;
+}
+
+int audio_spk_volume(void)
+{
+ return g_audio->spkvol_set;
+}
+
+int audio_spk_mute(void)
+{
+ return g_audio->spkmute_set;
+}
+#endif
+struct audio_data {
+ unsigned char *pData;
+ unsigned char *pPos;
+ unsigned char *pEnd;
+};
+
+int audio_send_data(void *args)
+{
+ struct audio_data *pAudio_usr = args;
+ struct audio_data pAudio;
+ char *data_buf = NULL;
+ int data_len = 0;
+ int i;
+ struct usb_request *req = NULL;
+
+ int len = g_audio->req_buf_size;
+ int send_len = 0;
+ int ret = 0;
+ int err = 0;
+
+ if (!uac_is_stream_on(1))
+ return 0;
+
+ ret = copy_from_user(&pAudio, pAudio_usr, sizeof(struct audio_data));
+ data_len = (unsigned int)pAudio.pEnd - (unsigned int)pAudio.pData;
+
+ if (data_len == 0) {
+ data_buf = kmalloc(32, GFP_KERNEL);
+ memset(data_buf, 0, 32);
+ pAudio.pEnd = data_buf + 32;
+ } else {
+ data_buf = kmalloc(data_len, GFP_KERNEL);
+ ret = copy_from_user(data_buf, pAudio.pData, data_len);
+ pAudio.pEnd = data_buf + data_len;
+ }
+ pAudio.pData = pAudio.pPos = data_buf;
+
+ for (i = 0; i < AUDIO_REQ_NUM; i++) {
+ if (g_audio->req_valid[i]) {
+ g_audio->req_valid[i] = 0;
+ req = g_audio->req[i];
+ req->buf = g_audio->req_buf[i];
+ req->context = (void *)i;
+ req->complete = f_audio_complete;
+
+ if (pAudio.pPos >= pAudio.pEnd) {
+ pAudio.pPos = pAudio.pData;
+ ret = 1;
+ break;
+ } else if (pAudio.pPos < pAudio.pData)
+ pAudio.pPos = pAudio.pData;
+
+ if (pAudio.pPos + g_audio->req_buf_size >= pAudio.pEnd) {
+ len = pAudio.pEnd-pAudio.pPos;
+ memcpy(req->buf, pAudio.pPos, len);
+ send_len += len;
+
+ pAudio.pPos = pAudio.pData;
+ ret = 1;
+ } else {
+ len = g_audio->req_buf_size;
+ memcpy(req->buf, pAudio.pPos, g_audio->req_buf_size);
+ pAudio.pPos += g_audio->req_buf_size;
+ send_len += g_audio->req_buf_size;
+ }
+ req->length = len;
+
+ err = usb_ep_queue(g_audio->ep, req, GFP_ATOMIC);
+ if (err)
+ UAC_ERR("audio usb_ep_queue error, %s req: %d\n", g_audio->ep->name, err);
+
+ if (ret)
+ break;
+ }
+ }
+
+ if (g_audio->sample_rate_set == 16000)
+ g_audio->req_buf_size = 32;
+ else if (g_audio->sample_rate_set == 8000)
+ g_audio->req_buf_size = 16;
+
+ kfree(data_buf);
+
+ if (data_len == 0)
+ return 0;
+
+ return send_len;
+
+}
+
+static int
+uac_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+ int cs, id;
+ int sendAudioReq = 0;
+ u8 *pData;
+
+ UAC_INFO("setup, req: %02x.%02x value: %04x index: %04x length: %d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+
+ g_audio->set_cmd = 0;
+
+ if ((ctrl->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE) {
+ value = 3;
+ sendAudioReq = 1;
+ cs = ctrl->wValue >> 8;
+ UAC_INFO("EndpointAddress = %x, id = %x, cs = %x\n",
+ audio_mic_streaming_ep.bEndpointAddress,
+ ctrl->wIndex, cs);
+ if (audio_mic_streaming_ep.bEndpointAddress == ctrl->wIndex && cs == 1)
+ g_audio->set_cmd = ctrl->wIndex;
+ } else {
+ cs = ctrl->wValue >> 8;
+ id = ctrl->wIndex >> 8;
+ UAC_INFO("id = %d, cs = %d\n", id, cs);
+ pData = req->buf;
+ if (id == FEATURE_UNIT_ID || id == SPEAKER_FU_ID) {
+ switch (cs) {
+ case UAC_FU_MUTE:
+ value = 1;
+ switch (ctrl->bRequest) {
+ case UAC_SET_CUR:
+ g_audio->set_cmd = cs;
+ g_audio->set_id = id;
+ break;
+
+ case UAC_GET_CUR:
+ if (id == FEATURE_UNIT_ID)
+ pData[0] = g_audio->mute_set;
+ if (id == SPEAKER_FU_ID)
+ pData[0] = g_audio->spkmute_set;
+ break;
+ }
+ break;
+
+ case UAC_FU_VOLUME:
+ value = 2;
+ switch (ctrl->bRequest) {
+ case UAC_SET_CUR:
+ g_audio->set_cmd = cs;
+ g_audio->set_id = id;
+ break;
+
+ case UAC_GET_CUR:
+ if (id == FEATURE_UNIT_ID) {
+ pData[0] = g_audio->vol_set & 0xff;
+ pData[1] = (g_audio->vol_set >> 8) & 0xff;
+ }
+ if (id == SPEAKER_FU_ID) {
+ pData[0] = g_audio->spkvol_set & 0xff;
+ pData[1] = (g_audio->spkvol_set >> 8) & 0xff;
+ }
+ break;
+
+ case UAC_GET_MIN:
+ pData[0] = 0x00;
+ pData[1] = 0x00;
+ break;
+
+ case UAC_GET_MAX:
+ if (id == FEATURE_UNIT_ID) {
+ pData[0] = UAC_MIC_MAX_GAIN & 0xff;
+ pData[1] = (UAC_MIC_MAX_GAIN >> 8) & 0xff;
+ }
+ if (id == SPEAKER_FU_ID) {
+ pData[0] = 0x64;
+ pData[1] = 0x00;
+ }
+ break;
+
+ case UAC_GET_RES:
+ pData[0] = 0x01;
+ pData[1] = 0x00;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
+ req->length = value;
+ req->zero = value < w_length;
+ req->complete = f_audio_complete;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0) {
+ DBG(cdev, "ep_queue --> %d\n", value);
+ req->status = 0;
+ }
+ }
+ if (sendAudioReq)
+ uac_begin_transfer_data();
+ return 0;
+}
+
+
+static int
+uac_function_get_alt(struct usb_function *f, unsigned int interface)
+{
+ UAC_INFO("get_alt\n");
+ return 0;
+}
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+static int uac_buffer_alloc(void)
+{
+ int i, err = 0;
+
+ g_audio->copy_buf =
+ f_audio_buffer_alloc(g_audio->audio_buf_size);
+ for (i = 0; i < AUDIO_REC_NUM && err == 0; i++) {
+
+ if (g_audio->out_req[i]) {
+ if (g_audio->out_req[i]->buf) {
+ g_audio->out_req[i]->length =
+ g_audio->req_speaker_buf_size;
+ g_audio->out_req[i]->context = g_audio;
+ g_audio->out_req[i]->complete =
+ f_audio_complete;
+ err = usb_ep_queue(g_audio->out_ep,
+ g_audio->out_req[i], GFP_ATOMIC);
+ if (err)
+ pr_err("%s queue req: %d\n",
+ g_audio->out_ep->name, err);
+ } else
+ err = -ENOMEM;
+ } else
+ err = -ENOMEM;
+ }
+ return err;
+}
+#endif
+
+static int
+uac_function_set_alt(struct usb_function *f,
+ unsigned int interface, unsigned int alt)
+{
+ int err = 0;
+
+ UAC_INFO("set_alt, intf = %d, alt = %d\n", interface, alt);
+ if (g_audio->as_mic_intf == interface)
+ uac_audio_enable(alt != 0, 1);
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ else if (g_audio->as_spk_intf == interface) {
+ uac_audio_enable(alt != 0, 2);
+ if (alt == 1) {
+ err = uac_buffer_alloc();
+ if (err < 0)
+ pr_err("uac buffer alloc failed!\n");
+ } else {
+ struct f_audio_buf *copy_buf = g_audio->copy_buf;
+
+ if (copy_buf)
+ f_audio_buffer_free(copy_buf);
+ g_audio->copy_buf = NULL;
+ }
+ }
+#endif
+ else if (g_audio->ac_intf == interface)
+ g_audio->ac_connected = 1;
+ return err;
+}
+
+static void
+uac_function_disable(struct usb_function *f)
+{
+
+ INFO(f->config->cdev, "uac_function_disable\n");
+}
+
+#define UVC_COPY_DESCRIPTOR(mem, dst, desc) \
+ do { \
+ memcpy(mem, desc, (desc)->bLength); \
+ *(dst)++ = mem; \
+ mem += (desc)->bLength; \
+ } while (0);
+
+#define UVC_COPY_DESCRIPTORS(mem, dst, src) \
+ do { \
+ const struct usb_descriptor_header * const *__src; \
+ for (__src = src; *__src; ++__src) { \
+ memcpy(mem, *__src, (*__src)->bLength); \
+ *dst++ = mem; \
+ mem += (*__src)->bLength; \
+ } \
+ } while (0)
+
+
+
+static struct usb_descriptor_header **
+uac_copy_descriptors(enum usb_device_speed speed)
+{
+ const struct usb_descriptor_header **src;
+ struct usb_descriptor_header **dst;
+ struct usb_descriptor_header **hdr;
+ unsigned int n_desc = 0;
+ unsigned int bytes = 0;
+ void *mem;
+
+ int audio_desc_num = 0;
+
+ for (src = (const struct usb_descriptor_header **)f_audio_descs;
+ *src; ++src) {
+ bytes += (*src)->bLength;
+ n_desc++;
+ }
+
+ audio_desc_num = (n_desc + 1) * sizeof(*src) + bytes;
+ UAC_INFO("copy_descriptors bytes = %d, ndesc = %d\n", bytes, n_desc);
+ mem = kmalloc(audio_desc_num+20, GFP_KERNEL);
+ hdr = mem;
+ dst = mem;
+ mem += (n_desc + 1) * sizeof(*src);
+
+ UVC_COPY_DESCRIPTORS(mem, dst,
+ (const struct usb_descriptor_header * const *)f_audio_descs);
+ *dst = (struct usb_descriptor_header *)NULL;
+ return hdr;
+
+}
+
+static void
+uac_function_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ audio_device_exit();
+}
+
+static int
+uac_function_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct usb_ep *ep;
+ int ret = -EINVAL;
+ int i;
+
+ UAC_DBG("bind~\n");
+
+ ep = usb_ep_autoconfig(cdev->gadget, &audio_mic_streaming_ep);
+ if (!ep) {
+ UAC_ERR("Unable to allocate audio EP\n");
+ goto error;
+ }
+
+ g_audio->ep = ep;
+
+
+ /* Allocate interface IDs. */
+ ret = usb_interface_id(c, f);
+ if (ret < 0)
+ goto error;
+
+ UAC_INFO("control_intf = %d\n", ret);
+ audio_iad_desc.bFirstInterface = ret;
+ ac_intf_desc.bInterfaceNumber = ret;
+ g_audio->ac_intf = ret;
+
+ ret = usb_interface_id(c, f);
+ if (ret < 0)
+ goto error;
+
+ UAC_INFO("streaming_intf = %d\n", ret);
+ as_mic_if_alt_0_desc.bInterfaceNumber = ret;
+ as_mic_if_alt_1_desc.bInterfaceNumber = ret;
+ g_audio->as_mic_intf = ret;
+ ac_header_desc.baInterfaceNr[0] = ret;
+
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+
+ ep = usb_ep_autoconfig(cdev->gadget, &audio_spk_streaming_ep);
+ UAC_DBG("audio_in_ep_id = %s\n", ep->name);
+ if (!ep) {
+ UAC_ERR("Unable to allocate audio EP\n");
+ goto error;
+ }
+ g_audio->out_ep = ep;
+ ret = usb_interface_id(c, f);
+ if (ret < 0)
+ goto error;
+
+ UAC_INFO("streaming_intf2 = %d\n", ret);
+ as_spk_if_alt_0_desc.bInterfaceNumber = ret;
+ as_spk_if_alt_1_desc.bInterfaceNumber = ret;
+ g_audio->as_spk_intf = ret;
+ ac_header_desc.baInterfaceNr[1] = ret;
+
+ g_audio->req_speaker_buf_size = 64;
+ g_audio->audio_buf_size = 640;
+ g_audio->copy_buf = NULL;
+ for (i = 0; i < AUDIO_REC_NUM; i++) {
+ g_audio->out_req[i] =
+ usb_ep_alloc_request(g_audio->out_ep, GFP_ATOMIC);
+ if (g_audio->out_req[i]) {
+ g_audio->out_req_buf[i] =
+ kzalloc(g_audio->req_speaker_buf_size, GFP_ATOMIC);
+ g_audio->out_req[i]->buf = g_audio->out_req_buf[i];
+ }
+ }
+ #endif
+ g_audio->vol_set = 75 * UAC_MIC_MAX_GAIN / 100;
+ g_audio->spkvol_set = 75;
+ /* Copy descriptors. */
+ f->fs_descriptors = uac_copy_descriptors(USB_SPEED_FULL);
+ f->hs_descriptors = uac_copy_descriptors(USB_SPEED_FULL);
+
+
+ g_audio->req_buf_size = 32;
+ for (i = 0; i < AUDIO_REQ_NUM; i++) {
+ g_audio->req[i] = usb_ep_alloc_request(g_audio->ep, GFP_ATOMIC);
+ if (g_audio->req[i]) {
+ g_audio->req_buf[i] =
+ kzalloc(g_audio->req_buf_size, GFP_ATOMIC);
+ g_audio->req[i]->buf = g_audio->req_buf[i];
+ }
+ }
+
+ return 0;
+
+error:
+ uac_function_unbind(c, f);
+ return ret;
+}
+
+
+
+
+
+
+int
+uac_bind_config(struct usb_configuration *c)
+{
+
+ int ret = 0;
+ struct usb_function *func;
+
+ /* Allocate string descriptor numbers. */
+ ret = usb_string_id(c->cdev);
+ if (ret < 0)
+ goto error;
+ uac_en_us_strings[UAC_STR_ASSOCIATION_IDX].id = ret;
+ audio_iad_desc.iFunction = ret;
+ ac_intf_desc.iInterface = ret;
+
+ ret = usb_string_id(c->cdev);
+ if (ret < 0)
+ goto error;
+ uac_en_us_strings[UAC_STR_STREAMING_IDX].id = ret;
+ as_mic_if_alt_0_desc.iInterface = ret;
+ as_mic_if_alt_1_desc.iInterface = ret;
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ as_spk_if_alt_0_desc.iInterface = ret;
+ as_spk_if_alt_1_desc.iInterface = ret;
+#endif
+
+ g_audio = kzalloc(sizeof(*g_audio), GFP_KERNEL);
+
+
+ func = kzalloc(sizeof(*func), GFP_KERNEL);
+
+ /* Register the function. */
+ func->name = "uac";
+ func->strings = uac_function_strings;
+ func->bind = uac_function_bind;
+ func->unbind = uac_function_unbind;
+ func->get_alt = uac_function_get_alt;
+ func->set_alt = uac_function_set_alt;
+ func->disable = uac_function_disable;
+ func->setup = uac_function_setup;
+
+ g_audio->func = func;
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ spin_lock_init(&g_audio->lock);
+ INIT_LIST_HEAD(&g_audio->play_queue);
+#endif
+
+ ret = usb_add_function(c, func);
+
+
+ audio_device_init();
+
+ return 0;
+
+error:
+ return ret;
+}
+
+
diff --git a/drivers/usb/gadget/function/f_uac.h b/drivers/usb/gadget/function/f_uac.h
new file mode 100644
index 00000000..268bcf5d
--- /dev/null
+++ b/drivers/usb/gadget/function/f_uac.h
@@ -0,0 +1,36 @@
+#ifndef _F_UAC_H_
+#define _F_UAC_H_
+
+#include <linux/usb/composite.h>
+#include <linux/poll.h>
+#include <linux/usb/audio.h>
+
+#define UAC_MIC_MAX_GAIN (0x64)
+
+struct f_audio_buf {
+ u8 *buf;
+ int actual;
+ struct list_head list;
+};
+
+extern void wake_up_app(void);
+extern int audio_device_init(void);
+extern void audio_device_exit(void);
+extern void uac_stream(int on);
+extern void uac_mic_FU(void);
+extern int audio_send_data(void *args);
+extern int audio_mic_simple_rate(void);
+extern int audio_mic_volume(void);
+extern int audio_mic_mute(void);
+
+extern int audio_recv_data(struct f_audio_buf *args);
+extern void wake_up_app_spk(void);
+extern void uac_stream_spk(int on);
+extern void uac_spk_FU(void);
+extern void speaker_dev_open(void);
+extern int audio_spk_simple_rate(void);
+extern int audio_spk_volume(void);
+extern int audio_spk_mute(void);
+
+
+#endif
\ No newline at end of file
diff --git a/drivers/usb/gadget/function/f_uac_poll.c b/drivers/usb/gadget/function/f_uac_poll.c
new file mode 100644
index 00000000..1c02b85d
--- /dev/null
+++ b/drivers/usb/gadget/function/f_uac_poll.c
@@ -0,0 +1,325 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/semaphore.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+
+#include "f_uac.h"
+
+
+#define init_MUTEX(LOCKNAME) sema_init(LOCKNAME, 1)
+#define DEVICE_NAME "uac_audio"
+#define DEVICE_NAME_SPK "uac_speaker"
+#define UAC_STREAM_OFF 0
+#define UAC_STREAM_ON 1
+#define UAC_IOC_SEND_AUDIO 0x499
+#define UAC_IOC_RECV_AUDIO 0x549
+#define UAC_IOC_GET_MIC_STREAM_STATUS 0x599
+#define UAC_IOC_GET_MIC_SIMPLE_STATUS 0x619
+#define UAC_IOC_GET_SPK_SIMPLE_STATUS 0x629
+#define UAC_IOC_GET_SPK_STREAM_STATUS 0x649
+
+#define UAC_IOC_GET_MIC_VOLUME_STATUS 0x650
+#define UAC_IOC_GET_MIC_MUTE_STATUS 0x651
+#define UAC_IOC_GET_SPK_VOLUME_STATUS 0x652
+#define UAC_IOC_GET_SPK_MUTE_STATUS 0x653
+
+
+
+static struct class *cdev_class;
+static struct cdev dev_c;
+static dev_t dev;
+
+static struct semaphore sem;
+static wait_queue_head_t outq;
+
+static int gStreamFlag;
+static int gStreamStatus = UAC_STREAM_OFF;
+static int gStaFlag;
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+static struct class *cdev_class_spk;
+static struct cdev dev_c_spk;
+static dev_t spk_dev;
+static wait_queue_head_t spkq;
+static int gStreamFlag_spk;
+static int gStreamStatus_spk = UAC_STREAM_OFF;
+static int gStaFlag_spk;
+#endif
+
+/*#define UAC_DEV_USE_LOCK*/
+static int lock(void)
+{
+#ifdef UAC_DEV_USE_LOCK
+ return down_interruptible(&sem);
+#else
+ return 0;
+#endif
+}
+
+static void unlock(void)
+{
+#ifdef UAC_DEV_USE_LOCK
+ up(&sem);
+#endif
+}
+
+
+void wake_up_app(void)
+{
+ if (gStreamStatus == UAC_STREAM_ON) {
+ lock();
+ gStreamFlag = 1;
+ unlock();
+ wake_up_interruptible(&outq);
+ }
+}
+
+
+void uac_stream(int on)
+{
+ lock();
+ gStreamStatus = on;
+ gStaFlag = 1;
+ unlock();
+ wake_up_interruptible(&outq);
+}
+
+void uac_mic_FU(void)
+{
+ lock();
+ gStaFlag = 1;
+ unlock();
+ wake_up_interruptible(&outq);
+}
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+void wake_up_app_spk(void)
+{
+ if (gStreamStatus_spk == UAC_STREAM_ON) {
+ lock();
+ gStreamFlag_spk = 1;
+ unlock();
+ wake_up_interruptible(&spkq);
+ }
+}
+
+void uac_stream_spk(int on)
+{
+ lock();
+ gStreamStatus_spk = on;
+ gStaFlag_spk = 1;
+ unlock();
+ wake_up_interruptible(&spkq);
+}
+
+void uac_spk_FU(void)
+{
+ lock();
+ gStaFlag_spk = 1;
+ unlock();
+ wake_up_interruptible(&spkq);
+}
+#endif
+
+static int audio_ops_open(struct inode *node, struct file *filp)
+{
+ return 0;
+}
+
+static long audio_ops_ioctl(struct file *filp,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case UAC_IOC_SEND_AUDIO:
+ return audio_send_data((void *)arg);
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ case UAC_IOC_RECV_AUDIO:
+ return audio_recv_data((struct f_audio_buf *)arg);
+
+ case UAC_IOC_GET_SPK_STREAM_STATUS:
+ return gStreamStatus_spk;
+
+ case UAC_IOC_GET_SPK_SIMPLE_STATUS:
+ return audio_spk_simple_rate();
+
+ case UAC_IOC_GET_SPK_VOLUME_STATUS:
+ return audio_spk_volume();
+
+ case UAC_IOC_GET_SPK_MUTE_STATUS:
+ return audio_spk_mute();
+#endif
+ case UAC_IOC_GET_MIC_STREAM_STATUS:
+ return gStreamStatus;
+
+ case UAC_IOC_GET_MIC_SIMPLE_STATUS:
+ return audio_mic_simple_rate();
+
+ case UAC_IOC_GET_MIC_VOLUME_STATUS:
+ return audio_mic_volume();
+
+ case UAC_IOC_GET_MIC_MUTE_STATUS:
+ return audio_mic_mute();
+
+ default:
+ pr_err("[UAC] %s audio ioctl cmd %x error!\n", __func__, cmd);
+ return -1;
+ }
+ return 0;
+}
+
+
+static unsigned int audio_ops_poll(struct file *filp, poll_table *wait)
+{
+ unsigned int mask = 0;
+ poll_wait(filp, &outq, wait);
+ lock();
+ if (gStreamFlag) {
+ if (gStreamStatus == UAC_STREAM_ON) {
+ /*Write Stream*/
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ gStreamFlag = 0;
+ }
+
+ if (gStaFlag) {
+ /*Read Status*/
+ mask |= POLLIN | POLLRDNORM;
+ gStaFlag = 0;
+ }
+ unlock();
+ return mask;
+}
+
+
+struct file_operations audio_device_fops = {
+poll:
+ audio_ops_poll,
+open :
+ audio_ops_open,
+unlocked_ioctl :
+ audio_ops_ioctl,
+};
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+static int speaker_ops_open(struct inode *node, struct file *filp)
+{
+ return 0;
+}
+
+static unsigned int speaker_ops_poll(struct file *filp, poll_table *wait)
+{
+ unsigned int mask = 0;
+ poll_wait(filp, &spkq, wait);
+ lock();
+ if (gStreamFlag_spk) {
+ if (gStreamStatus_spk == UAC_STREAM_ON) {
+ /*Write Stream*/
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ gStreamFlag_spk = 0;
+ }
+
+ if (gStaFlag_spk) {
+ /*Read Status*/
+ mask |= POLLIN | POLLRDNORM;
+ gStaFlag_spk = 0;
+ }
+ unlock();
+ return mask;
+}
+
+struct file_operations speaker_device_fops = {
+poll:
+ speaker_ops_poll,
+open :
+ speaker_ops_open,
+unlocked_ioctl :
+ audio_ops_ioctl,
+};
+#endif
+
+int audio_device_init(void)
+{
+ int ret, err;
+ /* mic */
+ ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
+ if (ret)
+ pr_err("audio device register failure");
+ else {
+ cdev_init(&dev_c, &audio_device_fops);
+ err = cdev_add(&dev_c, dev, 1);
+ if (err) {
+ pr_err("error %d adding FC_dev\n", err);
+ unregister_chrdev_region(dev, 1);
+ return err;
+ }
+
+
+ cdev_class = class_create(THIS_MODULE, DEVICE_NAME);
+ if (IS_ERR(cdev_class)) {
+ pr_err("ERR:cannot create a cdev_class\n");
+ unregister_chrdev_region(dev, 1);
+ return -1;
+ }
+ device_create(cdev_class, NULL, dev, 0, DEVICE_NAME);
+
+ init_MUTEX(&sem);
+ init_waitqueue_head(&outq);
+ }
+
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ /* speaker */
+ ret = alloc_chrdev_region(&spk_dev, 0, 1, DEVICE_NAME_SPK);
+ if (ret)
+ printk("speaker device register failure");
+ else {
+ cdev_init(&dev_c_spk, &speaker_device_fops);
+ err = cdev_add(&dev_c_spk, spk_dev, 1);
+ if (err) {
+ printk(KERN_NOTICE "error %d adding FC_dev\n", err);
+ unregister_chrdev_region(spk_dev, 1);
+ return err;
+ } else
+ printk("speaker device register success!\n");
+
+ cdev_class_spk = class_create(THIS_MODULE, DEVICE_NAME_SPK);
+ if (IS_ERR(cdev_class_spk)) {
+ printk("ERR:cannot create a cdev_class_spk\n");
+ unregister_chrdev_region(spk_dev, 1);
+ return -1;
+ }
+ device_create(cdev_class_spk,
+ NULL,
+ spk_dev,
+ 0,
+ DEVICE_NAME_SPK);
+
+ init_waitqueue_head(&spkq);
+ }
+#endif
+ return ret;
+}
+
+
+void audio_device_exit(void)
+{
+ device_destroy(cdev_class, dev);
+ class_destroy(cdev_class);
+ unregister_chrdev_region(dev, 1);
+#ifdef CONFIG_ENABLE_SPEAKER_DESC
+ device_destroy(cdev_class_spk, spk_dev);
+ class_destroy(cdev_class_spk);
+ unregister_chrdev_region(spk_dev, 1);
+#endif
+ /*printk("device");*/
+}
+
+
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index f8a18816..0b86532d 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -32,6 +32,11 @@
#include "uvc_configfs.h"
#include "uvc_v4l2.h"
#include "uvc_video.h"
+#include "uvc_format.h"
+
+#include "f_uac.c"
+#include "f_uac_poll.c"
+#include "f_uvc_fast.c"
unsigned int uvc_gadget_trace_param;
@@ -204,6 +209,23 @@ void uvc_set_trace_param(unsigned int trace)
}
EXPORT_SYMBOL(uvc_set_trace_param);
+
+void uvc_setup_to_demo(struct uvc_device *uvc)
+{
+#ifdef UVC_FASTBOOT
+ static bool first_ready;
+
+ if (first_ready == true) {
+ change_usb_support_fmt_fast(uvc);
+ uvc_function_connect(uvc);
+ }
+ first_ready = true;
+#endif
+
+ uvc->demo_ready = true;
+ pr_err("\n\nVIDIOC_UVC_DEMO_READY\n");
+}
+
/* --------------------------------------------------------------------------
* Control requests
*/
@@ -233,10 +255,11 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
- /* printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n",
- * ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue),
- * le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength));
- */
+/**
+ * printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n",
+ * ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue),
+ * le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength));
+ */
if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) {
INFO(f->config->cdev, "invalid request type\n");
@@ -256,8 +279,25 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_SETUP;
memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
+#ifndef UVC_FASTBOOT
v4l2_event_queue(&uvc->vdev, &v4l2_event);
+#else
+ static int uvc_enumdown;
+
+ if (ctrl->wIndex & 0xff)
+ uvc_enumdown = ctrl->wIndex;
+ if (!uvc_enumdown) {
+ uvc_events_process_class(uvc, ctrl);
+ } else {
+ if (uvc->demo_ready)
+ v4l2_event_queue(&uvc->vdev, &v4l2_event);
+ else {
+ pr_err("[UVC]WARNING:please open camera after demo ready!\n");
+ return -1;
+ }
+ }
+#endif
return 0;
}
@@ -269,7 +309,7 @@ void uvc_function_setup_continue(struct uvc_device *uvc)
}
static int
-uvc_function_get_alt(struct usb_function *f, unsigned interface)
+uvc_function_get_alt(struct usb_function *f, unsigned int interface)
{
struct uvc_device *uvc = to_uvc(f);
@@ -284,7 +324,7 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
}
static int
-uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
+uvc_function_set_alt(struct usb_function *f, unsigned int interface, unsigned alt)
{
struct uvc_device *uvc = to_uvc(f);
struct usb_composite_dev *cdev = f->config->cdev;
@@ -361,7 +401,8 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
v4l2_event_queue(&uvc->vdev, &v4l2_event);
- return USB_GADGET_DELAYED_STATUS;
+ // return USB_GADGET_DELAYED_STATUS;
+ return 0;
default:
return -EINVAL;
@@ -450,7 +491,7 @@ uvc_register_video(struct uvc_device *uvc)
} \
} while (0)
-static struct usb_descriptor_header **
+struct usb_descriptor_header **
uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
{
struct uvc_input_header_descriptor *uvc_streaming_header;
@@ -656,6 +697,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
goto error;
}
uvc->video.ep = ep;
+ uvc->video.ep->mult = max_packet_mult;
uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
@@ -739,6 +781,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
goto error;
}
+#ifdef CONFIG_UVC_INS_UAC
+ uac_bind_config(c);
+#endif
+
+#ifdef UVC_FASTBOOT
+ change_usb_support_fmt_fast(uvc);
+ uvc_function_connect(uvc);
+#endif
return 0;
error:
diff --git a/drivers/usb/gadget/function/f_uvc_fast.c b/drivers/usb/gadget/function/f_uvc_fast.c
new file mode 100644
index 00000000..5f0ef10f
--- /dev/null
+++ b/drivers/usb/gadget/function/f_uvc_fast.c
@@ -0,0 +1,330 @@
+
+// #include <linux/usb/ch9.h>
+// #include <linux/usb/gadget.h>
+// #include <linux/usb/video.h>
+// #include "uvc.h"
+
+#ifdef UVC_FASTBOOT
+
+struct uvc_control_value {
+ uint8_t max;
+ uint8_t min;
+ uint8_t cur;
+ uint8_t def;
+ uint8_t res; //resolution -> step
+};
+
+typedef void (*uvc_control_setup_call)(struct uvc_request_data *r); /* device -> host */
+typedef void (*uvc_control_data_call)(struct uvc_request_data *r); /* host -> device */
+
+struct uvc_control_ops {
+ uint8_t len;
+ struct uvc_control_value val;
+ uvc_control_setup_call fsetup;
+ uvc_control_data_call fdata;
+};
+
+static int
+uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
+{
+ struct usb_composite_dev *cdev = uvc->func.config->cdev;
+ struct usb_request *req = uvc->control_req;
+
+ if (data->length < 0)
+ return usb_ep_set_halt(cdev->gadget->ep0);
+
+ req->length = min_t(unsigned int, uvc->event_length, data->length);
+ req->zero = data->length < uvc->event_length;
+
+ memcpy(req->buf, data->data, req->length);
+
+ return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
+}
+
+static void
+uvc_interface_setup(uint8_t req, uint8_t cs,
+ struct uvc_request_data *resp)
+{
+ ;
+}
+
+static void pu_backlight_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_backlight_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+
+static void pu_brightness_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_brightness_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_contrast_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_contrast_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_gain_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_gain_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_power_freq_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_power_freq_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_hue_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_hue_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_saturation_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+
+static void pu_saturation_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+
+static void pu_sharpness_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+
+static void pu_sharpness_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+
+static void pu_gamma_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_gamma_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_temperature_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_temperature_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_temperature_auto_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_temperature_auto_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_component_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_component_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_component_auto_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_wb_component_auto_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_digital_multiplier_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_digital_multiplier_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_digital_limit_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_digital_limit_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_hue_auto_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_hue_auto_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_analog_video_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_analog_video_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_analog_lock_setup(struct uvc_request_data *r)
+{
+ ;
+}
+
+static void pu_analog_lock_data(struct uvc_request_data *r)
+{
+ ;
+}
+
+struct uvc_control_ops uvc_control_pu[] = {
+ /* len, max, min, cur, def, res, setup, data */
+ { 0, { 0, 0, 0, 0, 0}, NULL, NULL }, //UVC_PU_CONTROL_UNDEFINED
+ { 2, { 255, 0, 128, 128, 1 }, pu_backlight_setup, pu_backlight_data}, //UVC_PU_BACKLIGHT_COMPENSATION_CONTROL
+ { 2, { 180, 40, 128, 128, 1 }, pu_brightness_setup, pu_brightness_data}, //UVC_PU_BRIGHTNESS_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_contrast_setup, pu_contrast_data}, //UVC_PU_CONTRAST_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_gain_setup, pu_gain_data}, //UVC_PU_GAIN_CONTROL
+ { 1, { 255, 0, 128, 128, 1 }, pu_power_freq_setup, pu_power_freq_data}, //UVC_PU_POWER_LINE_FREQUENCY_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_hue_setup, pu_hue_data}, //UVC_PU_HUE_CONTROL
+ { 2, { 200, 0, 128, 128, 1 }, pu_saturation_setup, pu_saturation_data}, //UVC_PU_SATURATION_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_sharpness_setup, pu_sharpness_data}, //UVC_PU_SHARPNESS_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_gamma_setup, pu_gamma_data}, //UVC_PU_GAMMA_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_wb_temperature_setup, pu_wb_temperature_data}, //UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL
+ { 1, { 255, 0, 128, 128, 1 }, pu_wb_temperature_auto_setup, pu_wb_temperature_auto_data}, //UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL
+ { 4, { 255, 0, 128, 128, 1 }, pu_wb_component_setup, pu_wb_component_data}, //UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL
+ { 1, { 255, 0, 128, 128, 1 }, pu_wb_component_auto_setup, pu_wb_component_auto_data}, //UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_digital_multiplier_setup, pu_digital_multiplier_data}, //UVC_PU_DIGITAL_MULTIPLIER_CONTROL
+ { 2, { 255, 0, 128, 128, 1 }, pu_digital_limit_setup, pu_digital_limit_data}, //UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL
+ { 1, { 255, 0, 128, 128, 1 }, pu_hue_auto_setup, pu_hue_auto_data}, //UVC_PU_HUE_AUTO_CONTROL
+ { 1, { 255, 0, 128, 128, 1 }, pu_analog_video_setup, pu_analog_video_data}, //UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL
+ { 1, { 255, 0, 128, 128, 1 }, pu_analog_lock_setup, pu_analog_lock_data}, //UVC_PU_ANALOG_LOCK_STATUS_CONTROL
+};
+
+static void
+uvc_processing_unit_setup(uint8_t req, uint8_t cs,
+ struct uvc_request_data *resp)
+{
+ ;
+
+ resp->length = uvc_control_pu[cs].len;
+
+ switch (req) {
+ case UVC_GET_LEN:
+ resp->data[0] = resp->length;
+ break;
+
+ case UVC_GET_CUR:
+ /* if the value could be changed only in data phase,
+ * give the cur value directly */
+ //resp->data[0] = uvc_control_pu[cs].val.cur;
+ (*uvc_control_pu[cs].fsetup)(resp);
+ break;
+ case UVC_GET_MIN:
+ /* TODO diff type */
+ resp->data[0] = uvc_control_pu[cs].val.min;
+ break;
+ case UVC_GET_MAX:
+ resp->data[0] = uvc_control_pu[cs].val.max;
+ break;
+ case UVC_GET_DEF:
+ resp->data[0] = uvc_control_pu[cs].val.def;
+ break;
+ case UVC_GET_RES:
+ resp->data[0] = uvc_control_pu[cs].val.res;
+ break;
+ case UVC_GET_INFO:
+ resp->data[0] = cs;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+uvc_events_process_vc_setup(uint8_t req, uint8_t cs, uint8_t id,
+ struct uvc_request_data *resp)
+{
+ switch (id) {
+ case UVC_INTERFACE_ID:
+ uvc_interface_setup(req, cs, resp);
+ break;
+ case UVC_PROCESSING_UNIT_ID:
+ uvc_processing_unit_setup(req, cs, resp);
+ break;
+ default:
+ pr_err("# %s can not support termianl or UNIT id %d\n", __func__, id);
+ break;
+ }
+}
+
+void
+uvc_events_process_class(struct uvc_device *uvc, struct usb_ctrlrequest *ctrl)
+{
+ struct uvc_request_data resp;
+
+ memset(&resp, 0, sizeof resp);
+ resp.length = 0;
+
+ uvc_events_process_vc_setup(ctrl->bRequest, ctrl->wValue >> 8,
+ ctrl->wIndex >> 8, &resp);
+ uvc_send_response(uvc, &resp);
+
+}
+
+#endif
diff --git a/drivers/usb/gadget/function/g_zero.h b/drivers/usb/gadget/function/g_zero.h
index 492924d0..65cfafc9 100644
--- a/drivers/usb/gadget/function/g_zero.h
+++ b/drivers/usb/gadget/function/g_zero.h
@@ -14,27 +14,31 @@
#define GZERO_SS_ISO_QLEN 8
struct usb_zero_options {
- unsigned pattern;
- unsigned isoc_interval;
- unsigned isoc_maxpacket;
- unsigned isoc_mult;
- unsigned isoc_maxburst;
- unsigned bulk_buflen;
- unsigned qlen;
- unsigned ss_bulk_qlen;
- unsigned ss_iso_qlen;
+ unsigned int pattern;
+ unsigned int isoc_interval;
+ unsigned int isoc_maxpacket;
+ unsigned int isoc_mult;
+ unsigned int isoc_maxburst;
+ unsigned int bulk_buflen;
+ unsigned int qlen;
+ unsigned int ss_bulk_qlen;
+ unsigned int ss_iso_qlen;
};
struct f_ss_opts {
struct usb_function_instance func_inst;
- unsigned pattern;
- unsigned isoc_interval;
- unsigned isoc_maxpacket;
- unsigned isoc_mult;
- unsigned isoc_maxburst;
- unsigned bulk_buflen;
- unsigned bulk_qlen;
- unsigned iso_qlen;
+ unsigned int pattern;
+ unsigned int isoc_interval;
+ unsigned int isoc_maxpacket;
+ unsigned int isoc_mult;
+ unsigned int isoc_maxburst;
+ unsigned int bulk_buflen;
+ unsigned int bulk_qlen;
+ unsigned int iso_qlen;
+ unsigned int int_interval;
+ unsigned int int_maxpacket;
+ unsigned int int_maxburst;
+ unsigned int int_qlen;
/*
* Read/write access to configfs attributes is handled by configfs.
@@ -67,6 +71,7 @@ int lb_modinit(void);
/* common utilities */
void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out,
+ struct usb_ep *int_in, struct usb_ep *int_out,
struct usb_ep *iso_in, struct usb_ep *iso_out);
#endif /* __G_ZERO_H */
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index e0cd1e4c..67709861 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -1594,6 +1594,7 @@ static int userial_init(void)
}
module_init(userial_init);
+
static void userial_cleanup(void)
{
tty_unregister_driver(gs_tty_driver);
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index 7d3bb627..d27d8273 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -17,6 +17,8 @@
#include <linux/types.h>
#include <linux/usb/ch9.h>
+/* #define UVC_FASTBOOT */
+
#define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
@@ -26,6 +28,24 @@
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
+struct uvc_frame_info {
+ unsigned int width;
+ unsigned int height;
+ unsigned int intervals[8];
+};
+
+struct uvc_format_info {
+ unsigned int fcc;
+ const struct uvc_frame_info *frames;
+ unsigned int frame_num;
+};
+
+
+struct uvc_fmt_array_info {
+ unsigned int fmt_num;
+ struct uvc_format_info *pFmts;
+};
+
struct uvc_request_data
{
__s32 length;
@@ -42,6 +62,11 @@ struct uvc_event
};
#define UVCIOC_SEND_RESPONSE _IOW('U', 1, struct uvc_request_data)
+// #define VIDIOC_CONNECT_NOW _IOW('U', 3, struct uvc_device)
+#define VIDIOC_RESET_DESC 0x445566
+#define VIDIOC_CONNECT_NOW 0x238956
+#define VIDIOC_UVC_DEMO_READY 0x445567
+#define VIDIOC_DESC_GET 0x445568
#define UVC_INTF_CONTROL 0
#define UVC_INTF_STREAMING 1
@@ -164,6 +189,7 @@ struct uvc_device
void *control_buf;
unsigned int streaming_intf;
+ bool demo_ready;
/* Events */
unsigned int event_length;
@@ -193,6 +219,16 @@ extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);
extern void uvc_function_disconnect(struct uvc_device *uvc);
+extern void uvc_setup_to_demo(struct uvc_device *uvc);
+
+extern void set_yuv_bpp(int bpp);
+extern struct usb_descriptor_header **
+uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed);
+
+#ifdef UVC_FASTBOOT
+extern void uvc_events_process_class(struct uvc_device *uvc,
+ struct usb_ctrlrequest *ctrl);
+#endif
#endif /* __KERNEL__ */
diff --git a/drivers/usb/gadget/function/uvc_format.c b/drivers/usb/gadget/function/uvc_format.c
new file mode 100644
index 00000000..5dc1883a
--- /dev/null
+++ b/drivers/usb/gadget/function/uvc_format.c
@@ -0,0 +1,647 @@
+/*
+ * uvc_gadget.c -- USB Video Class Gadget driver
+ *
+ * Copyright (C) 2009-2010
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/video.h>
+
+#include "uvc.h"
+#include "uvc_format.h"
+
+
+#ifdef UVC_FASTBOOT
+
+#define YUY2_MAX_W 1280
+#define YUY2_MAX_H 720
+
+static const struct uvc_frame_info uvc_frames_nv12[] = {
+ { 640, 368, {333333, 400000, 0 }, },
+ { 640, 480, {333333, 400000, 0 }, },
+ { 1024, 576, {333333, 400000, 0 }, },
+ { YUY2_MAX_W, YUY2_MAX_H, {333333, 400000, 0 }, },
+ { 0, 0, { 0, }, },
+};
+
+static const struct uvc_frame_info uvc_frames_yuy2[] = {
+ { 640, 368, {333333, 400000, 0 }, },
+ { 640, 480, {333333, 400000, 0 }, },
+ { 1024, 576, {333333, 400000, 0 }, },
+ { YUY2_MAX_W, YUY2_MAX_H, {333333, 400000, 0 }, },
+ { 0, 0, { 0, }, },
+};
+
+static const struct uvc_frame_info uvc_frames_mjpeg[] = {
+ { 640, 480, {333333, 400000, 0 }, },
+ { 1280, 720, {333333, 400000, 0 }, },
+ { 1920, 1080, {333333, 400000, 0 }, },
+ { 1920, 1088, {333333, 400000, 0 }, },
+ { 2560, 1440, {333333, 400000, 0 }, },
+ { 0, 0, { 0, }, },
+};
+
+static const struct uvc_frame_info uvc_frames_h264[] = {
+ { 640, 480, {333333, 400000, 0 }, },
+ { 1280, 720, {333333, 400000, 0 }, },
+ { 1920, 1080, {333333, 400000, 0 }, },
+ { 2560, 1440, {333333, 400000, 0 }, },
+ { 0, 0, { 0, }, },
+};
+
+static const struct uvc_format_info uvc_formats[] = {
+ { V4L2_PIX_FMT_NV12, uvc_frames_nv12, ARRAY_SIZE(uvc_frames_nv12)},
+ { V4L2_PIX_FMT_YUY2, uvc_frames_yuy2, ARRAY_SIZE(uvc_frames_yuy2)},
+ { V4L2_PIX_FMT_MJPEG, uvc_frames_mjpeg, ARRAY_SIZE(uvc_frames_mjpeg)},
+ { V4L2_PIX_FMT_H264, uvc_frames_h264, ARRAY_SIZE(uvc_frames_h264)},
+};
+#endif
+
+#define YUV_NV12 0
+#define YUV_YUY2 1
+
+#define MAX_FRAME_DESCRIPTORS_NUM 10
+#define MAX_FRAME_INTERVAL_NUM 5
+
+struct uvc_frm_mjpg_info {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFrameIndex;
+ __u8 bmCapabilities;
+ __u16 wWidth;
+ __u16 wHeight;
+ __u32 dwMinBitRate;
+ __u32 dwMaxBitRate;
+ __u32 dwMaxVideoFrameBufferSize;
+ __u32 dwDefaultFrameInterval;
+ __u8 bFrameIntervalType;
+ __u32 dwFrameInterval[MAX_FRAME_INTERVAL_NUM];
+} __packed;
+
+
+struct uvc_frm_yuv_info {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFrameIndex;
+ __u8 bmCapabilities;
+ __u16 wWidth;
+ __u16 wHeight;
+ __u32 dwMinBitRate;
+ __u32 dwMaxBitRate;
+ __u32 dwMaxVideoFrameBufferSize;
+ __u32 dwDefaultFrameInterval;
+ __u8 bFrameIntervalType;
+ __u32 dwFrameInterval[MAX_FRAME_INTERVAL_NUM];
+} __packed;
+
+
+
+struct uvc_frm_h264_info {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFrameIndex;
+ __u8 bmCapabilities;
+ __u16 wWidth;
+ __u16 wHeight;
+ __u32 dwMinBitRate;
+ __u32 dwMaxBitRate;
+ __u32 dwDefaultFrameInterval;
+ __u8 bFrameIntervalType;
+ __u32 dwBytesPerLine;
+ __u32 dwFrameInterval[MAX_FRAME_INTERVAL_NUM];
+} __packed;
+
+DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 1);
+DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 5);
+
+struct uvc_fmt_array_data {
+ struct UVC_INPUT_HEADER_DESCRIPTOR(1, 5) uvc_input_header;
+ struct uvc_format_uncompressed uvc_format_nv12;
+ struct uvc_format_uncompressed uvc_format_yuy2;
+ struct uvc_format_mjpeg uvc_format_mjpg;
+ struct uvc_format_frameBased uvc_format_h264;
+ struct uvc_format_frameBased uvc_format_hevc;
+
+ struct uvc_frm_yuv_info yuv_frames[MAX_FRAME_DESCRIPTORS_NUM];
+ struct uvc_frm_yuv_info yuy2_frames[MAX_FRAME_DESCRIPTORS_NUM];
+ struct uvc_frm_mjpg_info mjpg_frames[MAX_FRAME_DESCRIPTORS_NUM];
+ struct uvc_frm_h264_info h264_frames[MAX_FRAME_DESCRIPTORS_NUM];
+ struct uvc_frm_h264_info hevc_frames[MAX_FRAME_DESCRIPTORS_NUM];
+ struct uvc_descriptor_header *uvc_streaming_data[MAX_FRAME_DESCRIPTORS_NUM*4];
+
+ int fmt_num;
+};
+
+static int uvc_stream_idx;
+static int uvc_fmt_idx = 1;
+static struct uvc_fmt_array_data *pCurFmtArray;
+static struct uvc_fmt_array_data uvc_fmt_array[2];
+
+
+
+static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 1) uvc_input_header = {
+ .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_INPUT_HEADER,
+ .bNumFormats = 1,
+ .wTotalLength = 0, /* dynamic */
+ .bEndpointAddress = 0, /* dynamic */
+ .bmInfo = 0,
+ .bTerminalLink = UVC_OUTPUT_TERMINAL_ID,
+ .bStillCaptureMethod = 0,
+ .bTriggerSupport = 0,
+ .bTriggerUsage = 0,
+ .bControlSize = 1,
+ .bmaControls[0][0] = 0,
+ // .bmaControls[1][0] = 4,
+};
+
+static /*const*/ struct uvc_format_uncompressed uvc_format_nv12 = {
+ .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
+ .bFormatIndex = 1,
+ .bNumFrameDescriptors = 3,
+ .guidFormat = { 'N', 'V', '1', '2',
+ 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00,
+ 0xaa, 0x00, 0x38, 0x9b, 0x71},
+ .bBitsPerPixel = 12,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterfaceFlags = 0,
+ .bCopyProtect = 0,
+};
+
+static /*const*/ struct uvc_format_uncompressed uvc_format_yuy2 = {
+ .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
+ .bFormatIndex = 1,
+ .bNumFrameDescriptors = 3,
+ .guidFormat = { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
+ .bBitsPerPixel = 16,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterfaceFlags = 0,
+ .bCopyProtect = 0,
+};
+
+static const struct uvc_format_mjpeg uvc_format_mjpg = {
+ .bLength = UVC_DT_FORMAT_MJPEG_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_MJPEG,
+ .bFormatIndex = 2,
+ .bNumFrameDescriptors = 2,
+ .bmFlags = 0,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterfaceFlags = 0,
+ .bCopyProtect = 0,
+};
+
+static const struct uvc_color_matching_descriptor uvc_color_matching = {
+ .bLength = UVC_DT_COLOR_MATCHING_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_COLORFORMAT,
+ .bColorPrimaries = 1,
+ .bTransferCharacteristics = 1,
+ .bMatrixCoefficients = 4,
+};
+
+static const struct uvc_format_frameBased uvc_format_h264 = {
+ .bLength = UVC_DT_FORMAT_FRAMEBASED_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED,
+ .bFormatIndex = 1,
+ .bNumFrameDescriptors = 1,
+ .guidFormat = { 'H', '2', '6', '4',
+ 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
+ 0x00, 0x38, 0x9b, 0x71},
+ .bBitsPerPixel = 16,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterfaceFlags = 0,
+ .bCopyProtect = 0,
+ .bVariableSize = 1,
+};
+
+static const struct uvc_format_frameBased uvc_format_hevc = {
+ .bLength = UVC_DT_FORMAT_FRAMEBASED_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED,
+ .bFormatIndex = 1,
+ .bNumFrameDescriptors = 1,
+ .guidFormat = {
+ 'H', '2', '6', '5', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
+ .bBitsPerPixel = 16,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterfaceFlags = 0,
+ .bCopyProtect = 0,
+ .bVariableSize = 1,
+};
+
+static int get_frame_array_num(const struct uvc_frame_info *pFrms)
+{
+ const struct uvc_frame_info *pFrmData = pFrms;
+ int num = 0;
+
+ while (1) {
+ if (pFrmData->width == 0)
+ break;
+ num++;
+ pFrmData++;
+ }
+
+ if (num > MAX_FRAME_DESCRIPTORS_NUM)
+ num = MAX_FRAME_DESCRIPTORS_NUM;
+
+ return num;
+}
+
+static int get_frame_intervals_num(const struct uvc_frame_info *pFrms)
+{
+ const struct uvc_frame_info *pFrmData = pFrms;
+ int num = 0;
+
+ while (1) {
+ if (pFrmData->intervals[num] == 0)
+ break;
+ num++;
+ }
+
+ if (num > MAX_FRAME_INTERVAL_NUM)
+ num = MAX_FRAME_INTERVAL_NUM;
+
+ return num;
+}
+
+static void
+ gen_yuv_frame_data(struct uvc_frm_yuv_info *pYuv,
+ int idx,
+ const struct uvc_frame_info *pFrm)
+{
+ int i;
+ int num = get_frame_intervals_num(pFrm);
+
+ pYuv->bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(num);
+ pYuv->bDescriptorType = USB_DT_CS_INTERFACE;
+ pYuv->bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED;
+ pYuv->bFrameIndex = idx;
+ pYuv->bmCapabilities = 0;
+ pYuv->wWidth = cpu_to_le16(pFrm->width);
+ pYuv->wHeight = cpu_to_le16(pFrm->height);
+ pYuv->dwMinBitRate = cpu_to_le32(18432000);
+ pYuv->dwMaxBitRate = cpu_to_le32(55296000);
+ pYuv->dwMaxVideoFrameBufferSize = cpu_to_le32(471040);
+ pYuv->dwDefaultFrameInterval = cpu_to_le32(pFrm->intervals[0]);
+
+ pYuv->bFrameIntervalType = num;
+ for (i = 0; i < num; i++)
+ pYuv->dwFrameInterval[i] =
+ cpu_to_le32(pFrm->intervals[i]);
+
+}
+
+static void
+gen_mjpg_frame_data(struct uvc_frm_mjpg_info *pMjpg,
+ int idx,
+ const struct uvc_frame_info *pFrm)
+{
+ int i;
+ int num = get_frame_intervals_num(pFrm);
+
+ pMjpg->bLength = UVC_DT_FRAME_MJPEG_SIZE(num);
+ pMjpg->bDescriptorType = USB_DT_CS_INTERFACE;
+ pMjpg->bDescriptorSubType = UVC_VS_FRAME_MJPEG;
+ pMjpg->bFrameIndex = idx;
+ pMjpg->bmCapabilities = 0;
+ pMjpg->wWidth = cpu_to_le16(pFrm->width);
+ pMjpg->wHeight = cpu_to_le16(pFrm->height);
+ pMjpg->dwMinBitRate = cpu_to_le32(18432000);
+ pMjpg->dwMaxBitRate = cpu_to_le32(55296000);
+ pMjpg->dwMaxVideoFrameBufferSize = cpu_to_le32(460800);
+ pMjpg->dwDefaultFrameInterval = cpu_to_le32(pFrm->intervals[0]);
+
+
+ pMjpg->bFrameIntervalType = num;
+ for (i = 0; i < num; i++)
+ pMjpg->dwFrameInterval[i] =
+ cpu_to_le32(pFrm->intervals[i]);
+
+}
+
+static void gen_h264_frame_data(struct uvc_frm_h264_info *pH264,
+ int idx,
+ const struct uvc_frame_info *pFrm)
+{
+ int i;
+ int num = get_frame_intervals_num(pFrm);
+
+ pH264->bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(num);
+ pH264->bDescriptorType = USB_DT_CS_INTERFACE;
+ pH264->bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED;
+ pH264->bFrameIndex = idx;
+ pH264->bmCapabilities = 0;
+ pH264->wWidth = cpu_to_le16(pFrm->width);
+ pH264->wHeight = cpu_to_le16(pFrm->height);
+ pH264->dwMinBitRate = cpu_to_le32(18432000);
+ pH264->dwMaxBitRate = cpu_to_le32(55296000);
+ pH264->dwDefaultFrameInterval = cpu_to_le32(pFrm->intervals[0]);
+ pH264->dwBytesPerLine = 0;
+
+ pH264->bFrameIntervalType = num;
+ for (i = 0; i < num; i++)
+ pH264->dwFrameInterval[i] = cpu_to_le32(pFrm->intervals[i]);
+
+}
+
+static void uvc_stream_append_data(void *data)
+{
+ pCurFmtArray->uvc_streaming_data[uvc_stream_idx++] =
+ (struct uvc_descriptor_header *)data;
+}
+
+static void deal_frms_array(unsigned int fcc, const struct uvc_frame_info *pFrms)
+{
+
+ int frm_num = get_frame_array_num(pFrms);
+ const struct uvc_frame_info *pFrmData = pFrms;
+ int i;
+
+ if (frm_num <= 0)
+ return;
+
+
+ switch (fcc) {
+ case V4L2_PIX_FMT_NV12:
+ uvc_stream_append_data(&pCurFmtArray->uvc_format_nv12);
+ pCurFmtArray->uvc_format_nv12.bFormatIndex = uvc_fmt_idx++;
+ pCurFmtArray->uvc_format_nv12.bNumFrameDescriptors = frm_num;
+ for (i = 0; i < frm_num; i++) {
+ gen_yuv_frame_data(&pCurFmtArray->yuv_frames[i],
+ i+1, pFrmData);
+ uvc_stream_append_data(&pCurFmtArray->yuv_frames[i]);
+ pFrmData++;
+ }
+ break;
+ case V4L2_PIX_FMT_YUY2:
+ uvc_stream_append_data(&pCurFmtArray->uvc_format_yuy2);
+ pCurFmtArray->uvc_format_yuy2.bFormatIndex = uvc_fmt_idx++;
+ pCurFmtArray->uvc_format_yuy2.bNumFrameDescriptors = frm_num;
+ for (i = 0; i < frm_num; i++) {
+ gen_yuv_frame_data(&pCurFmtArray->yuy2_frames[i], i+1, pFrmData);
+ uvc_stream_append_data(&pCurFmtArray->yuy2_frames[i]);
+ pFrmData++;
+ }
+ break;
+ case V4L2_PIX_FMT_MJPEG:
+ uvc_stream_append_data(&pCurFmtArray->uvc_format_mjpg);
+ pCurFmtArray->uvc_format_mjpg.bFormatIndex = uvc_fmt_idx++;
+ pCurFmtArray->uvc_format_mjpg.bNumFrameDescriptors = frm_num;
+ for (i = 0; i < frm_num; i++) {
+ gen_mjpg_frame_data(&pCurFmtArray->mjpg_frames[i],
+ i+1, pFrmData);
+ uvc_stream_append_data(&pCurFmtArray->mjpg_frames[i]);
+ pFrmData++;
+ }
+ break;
+
+ case V4L2_PIX_FMT_H264:
+ uvc_stream_append_data(&pCurFmtArray->uvc_format_h264);
+ pCurFmtArray->uvc_format_h264.bFormatIndex = uvc_fmt_idx++;
+ pCurFmtArray->uvc_format_h264.bNumFrameDescriptors = frm_num;
+ for (i = 0; i < frm_num; i++) {
+ gen_h264_frame_data(&pCurFmtArray->h264_frames[i],
+ i+1, pFrmData);
+ uvc_stream_append_data(&pCurFmtArray->h264_frames[i]);
+ pFrmData++;
+ }
+ break;
+ case V4L2_PIX_FMT_H265:
+ uvc_stream_append_data(&pCurFmtArray->uvc_format_hevc);
+ pCurFmtArray->uvc_format_hevc.bFormatIndex = uvc_fmt_idx++;
+ pCurFmtArray->uvc_format_hevc.bNumFrameDescriptors = frm_num;
+ for (i = 0; i < frm_num; i++) {
+ gen_h264_frame_data(&pCurFmtArray->hevc_frames[i], i+1, pFrmData);
+ uvc_stream_append_data(&pCurFmtArray->hevc_frames[i]);
+ pFrmData++;
+ }
+ break;
+ }
+}
+
+static void gen_uvc_fmt_array(int id, struct uvc_format_info *fmt, int fmt_num)
+{
+ struct uvc_format_info *pFmtData = fmt;
+ unsigned int i;
+
+ uvc_stream_idx = 0;
+ uvc_fmt_idx = 1;
+
+ pCurFmtArray = &uvc_fmt_array[id&0x01];
+ pCurFmtArray->fmt_num = fmt_num;
+ memcpy(&pCurFmtArray->uvc_input_header, &uvc_input_header,
+ sizeof(uvc_input_header));
+ memcpy(&pCurFmtArray->uvc_format_nv12, &uvc_format_nv12,
+ sizeof(uvc_format_nv12));
+ memcpy(&pCurFmtArray->uvc_format_yuy2, &uvc_format_yuy2,
+ sizeof(uvc_format_yuy2));
+ memcpy(&pCurFmtArray->uvc_format_mjpg, &uvc_format_mjpg,
+ sizeof(uvc_format_mjpg));
+ memcpy(&pCurFmtArray->uvc_format_h264, &uvc_format_h264,
+ sizeof(uvc_format_h264));
+ memcpy(&pCurFmtArray->uvc_format_hevc, &uvc_format_hevc,
+ sizeof(uvc_format_hevc));
+
+ uvc_stream_append_data((void *)&pCurFmtArray->uvc_input_header);
+ pCurFmtArray->uvc_input_header.bNumFormats = fmt_num;
+ pCurFmtArray->uvc_input_header.bLength = UVC_DT_INPUT_HEADER_SIZE(1, fmt_num);
+
+
+ for (i = 0; i < fmt_num; i++) {
+ deal_frms_array(pFmtData->fcc, pFmtData->frames);
+ pFmtData++;
+ }
+
+ uvc_stream_append_data((void *)&uvc_color_matching);
+ uvc_stream_append_data(NULL);
+}
+
+static void gen_stream_descriptor_array(struct uvc_fmt_array_info *pFai)
+{
+ gen_uvc_fmt_array(0, pFai->pFmts, pFai->fmt_num);
+}
+
+void change_usb_support_fmt(struct uvc_device *uvc, void *arg)
+{
+ struct usb_function *f;
+ struct uvc_fmt_array_info fai;
+ struct uvc_format_info *fmt, *m_fmt;
+ struct uvc_frame_info *frames;
+ int ret, i;
+
+ if (arg != NULL) {
+ ret = copy_from_user(&fai, arg, sizeof(struct uvc_fmt_array_info));
+ fmt = kmalloc(sizeof(struct uvc_format_info) * fai.fmt_num, GFP_KERNEL);
+ ret = copy_from_user(fmt, fai.pFmts, sizeof(struct uvc_format_info) * fai.fmt_num);
+ fai.pFmts = fmt;
+ m_fmt = fmt;
+
+ for (i = 0; i < fai.fmt_num; i++) {
+ frames = kmalloc(sizeof(struct uvc_frame_info) * fmt->frame_num, GFP_KERNEL);
+ ret = copy_from_user(frames, fmt->frames,
+ sizeof(struct uvc_frame_info) * fmt->frame_num);
+ fmt->frames = frames;
+ fmt++;
+ }
+
+ gen_stream_descriptor_array(&fai);
+ uvc->desc.fs_streaming =
+ (const struct uvc_descriptor_header * const *)uvc_fmt_array[0].uvc_streaming_data;
+ uvc->desc.hs_streaming =
+ (const struct uvc_descriptor_header * const *)uvc_fmt_array[0].uvc_streaming_data;
+ uvc->desc.ss_streaming =
+ (const struct uvc_descriptor_header * const *)uvc_fmt_array[0].uvc_streaming_data;
+ } else
+ pr_err("[UVC] VIDIOC_RESET_DESC arg is NULL!\n");
+ f = &uvc->func;
+ kfree(f->fs_descriptors);
+ /* Copy descriptors. */
+ f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
+ if (IS_ERR(f->fs_descriptors)) {
+ ret = PTR_ERR(f->fs_descriptors);
+ f->fs_descriptors = NULL;
+ return;
+ }
+ if (gadget_is_dualspeed(f->config->cdev->gadget)) {
+ kfree(f->hs_descriptors);
+ f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+ if (IS_ERR(f->hs_descriptors)) {
+ ret = PTR_ERR(f->hs_descriptors);
+ f->hs_descriptors = NULL;
+ return;
+ }
+ }
+ if (gadget_is_superspeed(f->config->cdev->gadget)) {
+ kfree(f->ss_descriptors);
+ f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
+ if (IS_ERR(f->ss_descriptors)) {
+ ret = PTR_ERR(f->ss_descriptors);
+ f->ss_descriptors = NULL;
+ return;
+ }
+ }
+ for (i = 0; i < fai.fmt_num; i++) {
+ kfree(m_fmt->frames);
+ m_fmt++;
+ }
+ kfree(fai.pFmts);
+}
+
+#ifdef UVC_FASTBOOT
+void change_usb_support_fmt_fast(struct uvc_device *uvc)
+{
+ struct usb_function *f;
+ struct uvc_fmt_array_info fai;
+ int ret;
+
+ fai.fmt_num = ARRAY_SIZE(uvc_formats);
+ fai.pFmts = (struct uvc_format_info *)uvc_formats;
+
+ gen_stream_descriptor_array(&fai);
+ uvc->desc.fs_streaming =
+ (const struct uvc_descriptor_header * const *)uvc_fmt_array[0].uvc_streaming_data;
+ uvc->desc.hs_streaming =
+ (const struct uvc_descriptor_header * const *)uvc_fmt_array[0].uvc_streaming_data;
+ uvc->desc.ss_streaming =
+ (const struct uvc_descriptor_header * const *)uvc_fmt_array[0].uvc_streaming_data;
+
+ f = &uvc->func;
+ kfree(f->fs_descriptors);
+ /* Copy descriptors. */
+ f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
+ if (IS_ERR(f->fs_descriptors)) {
+ ret = PTR_ERR(f->fs_descriptors);
+ f->fs_descriptors = NULL;
+ return;
+ }
+ if (gadget_is_dualspeed(f->config->cdev->gadget)) {
+ kfree(f->hs_descriptors);
+ f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
+ if (IS_ERR(f->hs_descriptors)) {
+ ret = PTR_ERR(f->hs_descriptors);
+ f->hs_descriptors = NULL;
+ return;
+ }
+ }
+ if (gadget_is_superspeed(f->config->cdev->gadget)) {
+ kfree(f->ss_descriptors);
+ f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
+ if (IS_ERR(f->ss_descriptors)) {
+ ret = PTR_ERR(f->ss_descriptors);
+ f->ss_descriptors = NULL;
+ return;
+ }
+ }
+}
+
+int usb_fmt_to_usr(struct uvc_device *uvc, void *arg)
+{
+ struct uvc_fmt_array_info fai;
+ struct uvc_format_info *fmt, *o_fmt, *m_fmt;
+ int ret, i;
+
+ if (arg != NULL) {
+ ret = copy_from_user(&fai, arg,
+ sizeof(struct uvc_fmt_array_info));
+ fmt = kmalloc(sizeof(struct uvc_format_info) * fai.fmt_num,
+ GFP_KERNEL);
+ ret = copy_from_user(fmt, fai.pFmts,
+ sizeof(struct uvc_format_info) * fai.fmt_num);
+ o_fmt = fmt;
+
+ m_fmt = fai.pFmts;
+ fai.fmt_num = ARRAY_SIZE(uvc_formats);
+
+ for (i = 0; i < fai.fmt_num; i++) {
+ fmt->fcc = uvc_formats[i].fcc;
+ fmt->frame_num = uvc_formats[i].frame_num;
+ ret = copy_to_user((void *)m_fmt, fmt,
+ sizeof(struct uvc_format_info));
+ ret = copy_to_user((void *)fmt->frames,
+ uvc_formats[i].frames,
+ sizeof(struct uvc_frame_info) *
+ uvc_formats[i].frame_num);
+
+ fmt++;
+ m_fmt++;
+ }
+ }
+ kfree(o_fmt);
+
+ return 0;
+
+}
+#endif
diff --git a/drivers/usb/gadget/function/uvc_format.h b/drivers/usb/gadget/function/uvc_format.h
new file mode 100644
index 00000000..b0f226f5
--- /dev/null
+++ b/drivers/usb/gadget/function/uvc_format.h
@@ -0,0 +1,16 @@
+#ifndef _UVC_FORMAT_H_
+#define _UVC_FORMAT_H_
+
+#ifdef __KERNEL__
+
+#include "uvc.h"
+
+extern void change_usb_support_fmt(struct uvc_device *uvc, void *arg);
+#ifdef UVC_FASTBOOT
+extern int usb_fmt_to_usr(struct uvc_device *uvc, void *arg);
+extern void change_usb_support_fmt_fast(struct uvc_device *uvc);
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _UVC_FORMAT_H_ */
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index f4ccbd56..5b4df2bb 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -27,6 +27,9 @@
#include "uvc_queue.h"
#include "uvc_video.h"
#include "uvc_v4l2.h"
+#include "uvc_format.h"
+
+#include <uapi/linux/videodev2.h>
/* --------------------------------------------------------------------------
* Requests handling
@@ -60,8 +63,11 @@ struct uvc_format
};
static struct uvc_format uvc_formats[] = {
- { 16, V4L2_PIX_FMT_YUYV },
- { 0, V4L2_PIX_FMT_MJPEG },
+ { 16, V4L2_PIX_FMT_YUY2 },
+ { 12, V4L2_PIX_FMT_NV12 },
+ { 0, V4L2_PIX_FMT_MJPEG },
+ { 0, V4L2_PIX_FMT_H264 },
+ { 0, V4L2_PIX_FMT_H265 },
};
static int
@@ -119,7 +125,7 @@ uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt)
}
if (i == ARRAY_SIZE(uvc_formats)) {
- printk(KERN_INFO "Unsupported format 0x%08x.\n",
+ printk(KERN_ERR "Unsupported format 0x%08x.\n",
fmt->fmt.pix.pixelformat);
return -EINVAL;
}
@@ -257,6 +263,23 @@ uvc_v4l2_ioctl_default(struct file *file, void *fh, bool valid_prio,
case UVCIOC_SEND_RESPONSE:
return uvc_send_response(uvc, arg);
+ case VIDIOC_RESET_DESC:
+ change_usb_support_fmt(uvc, arg);
+ return 0;
+
+#ifdef UVC_FASTBOOT
+ case VIDIOC_DESC_GET:
+ return usb_fmt_to_usr(uvc, arg);
+#endif
+
+ case VIDIOC_CONNECT_NOW:
+ uvc_function_connect(uvc);
+ return 0;
+
+ case VIDIOC_UVC_DEMO_READY:
+ uvc_setup_to_demo(uvc);
+ return 0;
+
default:
return -ENOIOCTLCMD;
}
@@ -298,6 +321,8 @@ uvc_v4l2_open(struct file *file)
handle->device = &uvc->video;
file->private_data = &handle->vfh;
+ return 0;
+
uvc_function_connect(uvc);
return 0;
}
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index 0f01c04d..57c63a83 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -244,7 +244,6 @@ uvc_video_alloc_requests(struct uvc_video *video)
req_size = video->ep->maxpacket
* max_t(unsigned int, video->ep->maxburst, 1)
* (video->ep->mult);
-
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
if (video->req_buffer[i] == NULL)
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
index 0b36878e..e7c71f53 100644
--- a/drivers/usb/gadget/legacy/Kconfig
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -474,6 +474,8 @@ config USB_G_WEBCAM
select USB_LIBCOMPOSITE
select VIDEOBUF2_VMALLOC
select USB_F_UVC
+ select USB_F_ACM
+ select USB_U_SERIAL
help
The Webcam Gadget acts as a composite USB Audio and Video Class
device. It provides a userspace API to process UVC control requests
diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c
index f9661cd6..b15e92a3 100644
--- a/drivers/usb/gadget/legacy/webcam.c
+++ b/drivers/usb/gadget/legacy/webcam.c
@@ -91,9 +91,9 @@ static struct usb_device_descriptor webcam_device_descriptor = {
.bNumConfigurations = 0, /* dynamic */
};
-DECLARE_UVC_HEADER_DESCRIPTOR(1);
+DECLARE_UVC_HEADER_DESCRIPTOR(2);
-static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = {
+static const struct UVC_HEADER_DESCRIPTOR(2) uvc_control_header = {
.bLength = UVC_DT_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_HEADER,
@@ -108,7 +108,7 @@ static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
.bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_INPUT_TERMINAL,
- .bTerminalID = 1,
+ .bTerminalID = UVC_CAMERAL_TERMINAL_ID,
.wTerminalType = cpu_to_le16(0x0201),
.bAssocTerminal = 0,
.iTerminal = 0,
@@ -116,7 +116,7 @@ static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = {
.wObjectiveFocalLengthMax = cpu_to_le16(0),
.wOcularFocalLength = cpu_to_le16(0),
.bControlSize = 3,
- .bmControls[0] = 2,
+ .bmControls[0] = 0x0a,
.bmControls[1] = 0,
.bmControls[2] = 0,
};
@@ -125,97 +125,60 @@ static const struct uvc_processing_unit_descriptor uvc_processing = {
.bLength = UVC_DT_PROCESSING_UNIT_SIZE(2),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_PROCESSING_UNIT,
- .bUnitID = 2,
- .bSourceID = 1,
+ .bUnitID = UVC_PROCESSING_UNIT_ID,
+ .bSourceID = UVC_CAMERAL_TERMINAL_ID,
.wMaxMultiplier = cpu_to_le16(16*1024),
.bControlSize = 2,
- .bmControls[0] = 1,
+ .bmControls[0] = 0x0b,
.bmControls[1] = 0,
.iProcessing = 0,
};
+DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(1, 1);
+
+static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 1) h264_extension_unit = {
+ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT,
+ .bUnitID = UVC_H264_EXTENSION_UNIT_ID,
+ .guidExtensionCode = { 0x41, 0x76, 0x9e, 0xa2, 0x04, 0xde, 0xe3,
+ 0x47, 0x8b, 0x2b, 0xf4, 0x34, 0x1a, 0xff, 0x88, 0x88},
+ .bNumControls = 17,
+ .bNrInPins = 1,
+ .baSourceID[0] = UVC_PROCESSING_UNIT_ID,
+ .bControlSize = 1,
+ .bmControls[0] = 0xff,
+ .iExtension = 0,
+};
+
static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
.bLength = UVC_DT_OUTPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL,
- .bTerminalID = 3,
+ .bTerminalID = UVC_OUTPUT_TERMINAL_ID,
.wTerminalType = cpu_to_le16(0x0101),
.bAssocTerminal = 0,
- .bSourceID = 2,
+ .bSourceID = UVC_H264_EXTENSION_UNIT_ID,
.iTerminal = 0,
};
-DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2);
+DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 1);
-static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = {
- .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 2),
+static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 1) uvc_input_header = {
+ .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VS_INPUT_HEADER,
- .bNumFormats = 2,
+ .bNumFormats = 1,
.wTotalLength = 0, /* dynamic */
.bEndpointAddress = 0, /* dynamic */
.bmInfo = 0,
- .bTerminalLink = 3,
+ .bTerminalLink = UVC_OUTPUT_TERMINAL_ID,
.bStillCaptureMethod = 0,
.bTriggerSupport = 0,
.bTriggerUsage = 0,
.bControlSize = 1,
.bmaControls[0][0] = 0,
- .bmaControls[1][0] = 4,
-};
-
-static const struct uvc_format_uncompressed uvc_format_yuv = {
- .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE,
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
- .bFormatIndex = 1,
- .bNumFrameDescriptors = 2,
- .guidFormat =
- { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
- 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
- .bBitsPerPixel = 16,
- .bDefaultFrameIndex = 1,
- .bAspectRatioX = 0,
- .bAspectRatioY = 0,
- .bmInterfaceFlags = 0,
- .bCopyProtect = 0,
-};
-
-DECLARE_UVC_FRAME_UNCOMPRESSED(1);
-DECLARE_UVC_FRAME_UNCOMPRESSED(3);
-
-static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
- .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
- .bFrameIndex = 1,
- .bmCapabilities = 0,
- .wWidth = cpu_to_le16(640),
- .wHeight = cpu_to_le16(360),
- .dwMinBitRate = cpu_to_le32(18432000),
- .dwMaxBitRate = cpu_to_le32(55296000),
- .dwMaxVideoFrameBufferSize = cpu_to_le32(460800),
- .dwDefaultFrameInterval = cpu_to_le32(666666),
- .bFrameIntervalType = 3,
- .dwFrameInterval[0] = cpu_to_le32(666666),
- .dwFrameInterval[1] = cpu_to_le32(1000000),
- .dwFrameInterval[2] = cpu_to_le32(5000000),
-};
-
-static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
- .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
- .bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
- .bFrameIndex = 2,
- .bmCapabilities = 0,
- .wWidth = cpu_to_le16(1280),
- .wHeight = cpu_to_le16(720),
- .dwMinBitRate = cpu_to_le32(29491200),
- .dwMaxBitRate = cpu_to_le32(29491200),
- .dwMaxVideoFrameBufferSize = cpu_to_le32(1843200),
- .dwDefaultFrameInterval = cpu_to_le32(5000000),
- .bFrameIntervalType = 1,
- .dwFrameInterval[0] = cpu_to_le32(5000000),
+ // .bmaControls[1][0] = 4,
};
static const struct uvc_format_mjpeg uvc_format_mjpg = {
@@ -282,6 +245,7 @@ static const struct uvc_descriptor_header * const uvc_fs_control_cls[] = {
(const struct uvc_descriptor_header *) &uvc_control_header,
(const struct uvc_descriptor_header *) &uvc_camera_terminal,
(const struct uvc_descriptor_header *) &uvc_processing,
+ (const struct uvc_descriptor_header *) &h264_extension_unit,
(const struct uvc_descriptor_header *) &uvc_output_terminal,
NULL,
};
@@ -290,15 +254,13 @@ static const struct uvc_descriptor_header * const uvc_ss_control_cls[] = {
(const struct uvc_descriptor_header *) &uvc_control_header,
(const struct uvc_descriptor_header *) &uvc_camera_terminal,
(const struct uvc_descriptor_header *) &uvc_processing,
+ (const struct uvc_descriptor_header *) &h264_extension_unit,
(const struct uvc_descriptor_header *) &uvc_output_terminal,
NULL,
};
static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
- (const struct uvc_descriptor_header *) &uvc_format_yuv,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
@@ -308,9 +270,6 @@ static const struct uvc_descriptor_header * const uvc_fs_streaming_cls[] = {
static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
- (const struct uvc_descriptor_header *) &uvc_format_yuv,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
@@ -320,9 +279,6 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = {
static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
- (const struct uvc_descriptor_header *) &uvc_format_yuv,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
@@ -333,6 +289,10 @@ static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
/* --------------------------------------------------------------------------
* USB configuration
*/
+#ifdef CONFIG_UVC_ACM_COM
+static struct usb_function_instance *fi_serial;
+static struct usb_function *f_serial;
+#endif
static int
webcam_config_bind(struct usb_configuration *c)
@@ -347,6 +307,20 @@ webcam_config_bind(struct usb_configuration *c)
if (status < 0)
usb_put_function(f_uvc);
+#ifdef CONFIG_UVC_ACM_COM
+ fi_serial = usb_get_function_instance("acm");
+ if (IS_ERR(fi_serial))
+ return status;
+
+ f_serial = usb_get_function(fi_serial);
+ if (IS_ERR(f_serial))
+ return status;
+
+ status = usb_add_function(c, f_serial);
+ if (status < 0)
+ usb_put_function(status);
+#endif
+
return status;
}
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index e31f72b3..fc490cca 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1708,7 +1708,7 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb)
return 0;
}
-static int halt_simple(struct usbtest_dev *dev)
+static int halt_simple(struct usbtest_dev *dev, int start)
{
int ep;
int retval = 0;
@@ -1722,6 +1722,23 @@ static int halt_simple(struct usbtest_dev *dev)
if (urb == NULL)
return -ENOMEM;
+ if (start) {
+ struct completion completion;
+
+ init_completion(&completion);
+ urb->context = &completion;
+ urb->pipe = dev->in_pipe;
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ if (retval == 0) {
+ if (!wait_for_completion_timeout(&completion,
+ msecs_to_jiffies(SIMPLE_IO_TIMEOUT))) {
+ usb_kill_urb(urb);
+ return -ETIMEDOUT;
+ }
+ } else
+ return retval;
+ }
+
if (dev->in_pipe) {
ep = usb_pipeendpoint(dev->in_pipe) | USB_DIR_IN;
urb->pipe = dev->in_pipe;
@@ -2292,10 +2309,10 @@ usbtest_do_ioctl(struct usb_interface *intf, struct usbtest_param_32 *param)
break;
retval = 0;
dev_info(&intf->dev, "TEST 12: unlink %d writes of %d\n",
- param->iterations, param->length);
+ param->iterations, param->length*2);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
retval = unlink_simple(dev, dev->out_pipe,
- param->length);
+ param->length*2);
if (retval)
dev_err(&intf->dev, "unlink writes failed %d, "
"iterations left %d\n", retval, i);
@@ -2309,7 +2326,7 @@ usbtest_do_ioctl(struct usb_interface *intf, struct usbtest_param_32 *param)
dev_info(&intf->dev, "TEST 13: set/clear %d halts\n",
param->iterations);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
- retval = halt_simple(dev);
+ retval = halt_simple(dev, i == param->iterations-1);
if (retval)
ERROR(dev, "halts failed, iterations left %d\n", i);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 8f8909a6..a0783ca3 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -834,6 +834,14 @@ config GEODE_WDT
You can compile this driver directly into the kernel, or use
it as a module. The module will be called geodewdt.
+
+config FH_WATCHDOG
+ tristate "fullhan watchdog driver"
+
+ help
+ A software monitoring watchdog and NMI sourcing driver.
+
+
config SC520_WDT
tristate "AMD Elan SC520 processor Watchdog"
depends on MELAN
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4aa..3b20dc0b 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o
obj-$(CONFIG_RENESAS_WDT) += renesas_wdt.o
obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
+obj-$(CONFIG_FH_WATCHDOG) += fh_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/fh_wdt.c b/drivers/watchdog/fh_wdt.c
new file mode 100644
index 00000000..9f3354a6
--- /dev/null
+++ b/drivers/watchdog/fh_wdt.c
@@ -0,0 +1,511 @@
+/*
+ * FH wdt subsystem
+ *
+ * Copyright (C) 2014 Fullhan Microelectronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#define pr_fmt(fmt) "fh_wdt: " fmt
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <mach/pmu.h>
+#include <mach/fh_wdt_plat.h>
+
+/* RMOD will cause a interrupt */
+#define WDT_RESPONSE_MODE
+
+#define WDOG_CONTROL_REG_OFFSET 0x00
+#define WDOG_CONTROL_REG_WDT_EN_MASK 0x01
+#define WDOG_CONTROL_REG_RMOD_MASK 0x02
+#define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04
+#define WDOG_CURRENT_COUNT_REG_OFFSET 0x08
+#define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c
+#define WDOG_COUNTER_RESTART_KICK_VALUE 0x76
+
+/* Hardware timeout in seconds */
+#define WDT_HW_TIMEOUT 2
+/* User land timeout */
+#define WDT_HEARTBEAT 15
+static int heartbeat = WDT_HEARTBEAT;
+
+/* The maximum TOP (timeout period) value that can be set in the watchdog. */
+#define FH_WDT_MAX_TOP 15
+#define WDT_CLOCK clk_get_rate(fh_wdt.clk)
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define WDT_TIMEOUT (HZ / 2)
+
+struct fh_wdt_drv {
+ spinlock_t lock;
+ void __iomem *regs;
+ struct clk *clk;
+ int mode;
+ unsigned long in_use;
+ unsigned long next_heartbeat;
+ struct timer_list timer;
+ int expect_close;
+};
+
+struct fh_wdt_drv fh_wdt;
+
+static inline int fh_wdt_is_enabled(void)
+{
+ return readl(fh_wdt.regs + WDOG_CONTROL_REG_OFFSET) &
+ WDOG_CONTROL_REG_WDT_EN_MASK;
+}
+
+static inline int fh_wdt_top_in_seconds(unsigned int top)
+{
+ /*
+ * There are 16 possible timeout values in 0..15 where the number of
+ * cycles is 2 ^ (16 + i) and the watchdog counts down.
+ */
+ return (1 << (16 + top)) / WDT_CLOCK;
+}
+
+static inline void fh_wdt_set_next_heartbeat(void)
+{
+ fh_wdt.next_heartbeat = jiffies + heartbeat * HZ;
+}
+
+static int fh_wdt_set_top(unsigned int top_s)
+{
+ int i, val, top_val = FH_WDT_MAX_TOP;
+ /*
+ * Iterate over the timeout values until we find the closest match. We
+ * always look for >=.
+ */
+
+ for (i = 0; i <= FH_WDT_MAX_TOP; ++i)
+ if (fh_wdt_top_in_seconds(i) >= top_s) {
+ top_val = i;
+ break;
+ }
+
+ /* Set the new value in the watchdog. */
+ pr_info("[wdt] set topval: %d", top_val);
+ writel(top_val, fh_wdt.regs + WDOG_TIMEOUT_RANGE_REG_OFFSET);
+
+ fh_wdt_set_next_heartbeat();
+ val = fh_wdt_top_in_seconds(top_val);
+
+ return val;
+}
+
+static void fh_wdt_keepalive(void)
+{
+ writel(WDOG_COUNTER_RESTART_KICK_VALUE, fh_wdt.regs +
+ WDOG_COUNTER_RESTART_REG_OFFSET);
+}
+
+static void fh_wdt_ping(unsigned long data)
+{
+ if (time_before(jiffies, fh_wdt.next_heartbeat) ||
+ (!nowayout && !fh_wdt.in_use)) {
+ fh_wdt_keepalive();
+ mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT);
+ } else
+ pr_crit("keepalive missed, machine will reset\n");
+}
+
+static int fh_wdt_open(struct inode *inode, struct file *filp)
+{
+ if (test_and_set_bit(0, &fh_wdt.in_use))
+ return -EBUSY;
+
+ /* Make sure we don't get unloaded. */
+ __module_get(THIS_MODULE);
+
+ spin_lock(&fh_wdt.lock);
+
+ fh_pmu_wdt_resume();
+
+ fh_wdt_set_top(WDT_HW_TIMEOUT);
+ if (!fh_wdt_is_enabled()) {
+/*
+ * The watchdog is not currently enabled. Set the timeout to
+ * the maximum and then start it.
+ */
+ u32 value;
+
+ value = WDOG_CONTROL_REG_WDT_EN_MASK;
+#ifdef WDT_RESPONSE_MODE
+ value |= WDOG_CONTROL_REG_RMOD_MASK;
+#endif
+ writel(value, fh_wdt.regs + WDOG_CONTROL_REG_OFFSET);
+ fh_wdt_keepalive();
+ }
+
+ if (fh_wdt.mode == MODE_DISCRETE)
+ del_timer(&fh_wdt.timer);
+
+ spin_unlock(&fh_wdt.lock);
+
+ return nonseekable_open(inode, filp);
+}
+
+ssize_t fh_wdt_write(struct file *filp, const char __user *buf, size_t len,
+ loff_t *offset)
+{
+ if (!len)
+ return 0;
+
+ if (!nowayout) {
+ size_t i;
+
+ fh_wdt.expect_close = 0;
+
+ for (i = 0; i < len; ++i) {
+ char c;
+
+ if (get_user(c, buf + i))
+ return -EFAULT;
+
+ if (c == 'V') {
+ fh_wdt.expect_close = 1;
+ break;
+ }
+ }
+ }
+
+ if (fh_wdt.mode == MODE_CONTINUOUS) {
+ fh_wdt_set_next_heartbeat();
+ mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT);
+ } else
+ fh_wdt_keepalive();
+
+ return len;
+}
+
+static u32 fh_wdt_time_left(void)
+{
+ return readl(fh_wdt.regs + WDOG_CURRENT_COUNT_REG_OFFSET) /
+ WDT_CLOCK;
+}
+
+static const struct watchdog_info fh_wdt_ident = {
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE,
+ .identity = "Synopsys DesignWare Watchdog",
+};
+
+static long fh_wdt_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ unsigned long val;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user((struct watchdog_info *)arg, &fh_wdt_ident,
+ sizeof(fh_wdt_ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int *)arg);
+
+ case WDIOC_KEEPALIVE:
+ if (fh_wdt.mode == MODE_CONTINUOUS)
+ fh_wdt_set_next_heartbeat();
+ else
+ fh_wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+
+ if (fh_wdt.mode == MODE_CONTINUOUS) {
+ heartbeat = val;
+ fh_wdt_set_next_heartbeat();
+ fh_wdt_keepalive();
+ } else {
+ fh_wdt_set_top(val);
+ fh_wdt_keepalive();
+ }
+
+ return put_user(val, (int __user *)arg);
+ case WDIOC_GETTIMEOUT:
+ return put_user((fh_wdt.mode == MODE_CONTINUOUS) ?
+ heartbeat : fh_wdt_time_left(), (int __user *)arg);
+ case WDIOC_GETTIMELEFT:
+ /* Get the time left in hardware if use hardware-mode*/
+ if (fh_wdt.mode == MODE_CONTINUOUS)
+ val = (fh_wdt.next_heartbeat
+ - fh_wdt.timer.expires) / HZ;
+ else
+ val = fh_wdt_time_left();
+
+ return put_user(val, (int __user *)arg);
+ case WDIOC_SETOPTIONS:
+ if (get_user(val, (int __user *)arg))
+ return -EFAULT;
+
+ if (val & WDIOS_DISABLECARD) {
+ fh_pmu_wdt_pause();
+ }
+
+ if (val & WDIOS_ENABLECARD) {
+ fh_pmu_wdt_resume();
+ }
+
+ return 0;
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+#ifdef WDT_RESPONSE_MODE
+static irqreturn_t fh_wdt_interrupt(int this_irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+#endif
+
+static int fh_wdt_release(struct inode *inode, struct file *filp)
+{
+ clear_bit(0, &fh_wdt.in_use);
+
+ if (!fh_wdt.expect_close && (fh_wdt.mode == MODE_CONTINUOUS)) {
+ del_timer(&fh_wdt.timer);
+ if (!nowayout)
+ pr_crit("unexpected close, system will reboot soon\n");
+ else
+ pr_crit("watchdog cannot be disabled, system will reboot soon\n");
+ }
+
+ fh_wdt.expect_close = 0;
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int fh_wdt_suspend(struct device *dev)
+{
+ fh_pmu_wdt_pause();
+ return 0;
+}
+
+static int fh_wdt_resume(struct device *dev)
+{
+ fh_pmu_wdt_resume();
+ fh_wdt_keepalive();
+ return 0;
+}
+
+static const struct dev_pm_ops fh_wdt_pm_ops = {
+ .suspend = fh_wdt_suspend,
+ .resume = fh_wdt_resume,
+};
+
+#endif /* CONFIG_PM */
+
+static const struct file_operations wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = fh_wdt_open,
+ .write = fh_wdt_write,
+ .unlocked_ioctl = fh_wdt_ioctl,
+ .release = fh_wdt_release
+};
+
+static struct miscdevice fh_wdt_miscdev = {
+ .fops = &wdt_fops,
+ .name = "watchdog",
+ .minor = WATCHDOG_MINOR,
+};
+
+#ifdef CONFIG_USE_OF
+static struct of_device_id const fh_wdt_of_match[] = {
+ {
+ .compatible = "fh,fh-wdt",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fh_wdt_of_match);
+#endif
+
+static int fh_wdt_drv_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int irq;
+#ifdef CONFIG_USE_OF
+ const struct of_device_id *match;
+ struct device_node *np = pdev->dev.of_node;
+#else
+ struct resource *mem;
+ struct fh_wdt_platform_data *pdata;
+#endif
+
+#ifdef CONFIG_USE_OF
+ match = of_match_device(fh_wdt_of_match, &pdev->dev);
+ if (!match) {
+ pr_info("failed to find wdt!\n");
+ return -ENODEV;
+ }
+
+ fh_wdt.regs = of_iomap(np, 0);
+ if (fh_wdt.regs == NULL) {
+ ret = -ENOMEM;
+ return ret;
+ }
+
+#ifdef WDT_RESPONSE_MODE
+ irq = irq_of_parse_and_map(np, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ ret = -ENXIO;
+ goto release_region;
+ }
+
+ ret = request_irq(irq, fh_wdt_interrupt, IRQF_NO_THREAD, "wdt",
+ &fh_wdt);
+ if (ret) {
+ dev_err(&pdev->dev, "failure requesting irq %i\n", irq);
+ ret = -ENXIO;
+ goto release_irq_mapping;
+ }
+#endif
+ of_property_read_u32(np, "mode", &fh_wdt.mode);
+#else
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!mem)
+ return -EINVAL;
+
+ if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+ "fh_wdt"))
+ return -ENOMEM;
+
+ fh_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ if (!fh_wdt.regs)
+ return -ENOMEM;
+
+#ifdef WDT_RESPONSE_MODE
+ irq = irq_create_mapping(NULL, platform_get_irq(pdev, 0));
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ goto release_region;
+ }
+
+ ret = request_irq(irq, fh_wdt_interrupt, IRQF_NO_THREAD, "wdt",
+ &fh_wdt);
+ if (ret) {
+ dev_err(&pdev->dev, "failure requesting irq %i\n", irq);
+ goto release_irq_mapping;
+ }
+#endif
+
+ pdata = (struct fh_wdt_platform_data *) pdev->dev.platform_data;
+ if (pdata)
+ fh_wdt.mode = pdata->mode;
+ else
+ fh_wdt.mode = MODE_CONTINUOUS;
+
+#endif
+
+ fh_wdt.clk = clk_get(NULL, "wdt_clk");
+
+ if (IS_ERR(fh_wdt.clk))
+ return PTR_ERR(fh_wdt.clk);
+
+ clk_set_rate(fh_wdt.clk, 1000000);
+
+ ret = clk_prepare_enable(fh_wdt.clk);
+ if (ret)
+ goto out_put_clk;
+
+ spin_lock_init(&fh_wdt.lock);
+ ret = misc_register(&fh_wdt_miscdev);
+ if (ret)
+ goto out_disable_clk;
+ fh_wdt_set_next_heartbeat();
+ setup_timer(&fh_wdt.timer, fh_wdt_ping, 0);
+ mod_timer(&fh_wdt.timer, jiffies + WDT_TIMEOUT);
+
+ return 0;
+
+out_disable_clk:
+ clk_disable(fh_wdt.clk);
+out_put_clk:
+ clk_put(fh_wdt.clk);
+release_irq_mapping:
+ irq_dispose_mapping(irq);
+ free_irq(irq, &pdev->dev);
+#ifdef WDT_RESPONSE_MODE
+release_region:
+#endif
+ iounmap(fh_wdt.regs);
+
+ return ret;
+}
+
+static int fh_wdt_drv_remove(struct platform_device *pdev)
+{
+ misc_deregister(&fh_wdt_miscdev);
+
+ clk_disable(fh_wdt.clk);
+ clk_put(fh_wdt.clk);
+
+ return 0;
+}
+
+
+
+static struct platform_driver fh_wdt_driver = {
+ .probe = fh_wdt_drv_probe,
+ .remove = fh_wdt_drv_remove,
+ .driver = {
+ .name = "fh_wdt",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &fh_wdt_pm_ops,
+#endif /* CONFIG_PM */
+#ifdef CONFIG_USE_OF
+ .of_match_table = fh_wdt_of_match,
+#endif
+ },
+};
+
+static int __init fh_wdt_watchdog_init(void)
+{
+ return platform_driver_register(&fh_wdt_driver);
+}
+module_init(fh_wdt_watchdog_init);
+
+static void __exit fh_wdt_watchdog_exit(void)
+{
+ platform_driver_unregister(&fh_wdt_driver);
+}
+module_exit(fh_wdt_watchdog_exit);
+
+MODULE_AUTHOR("fullhan");
+MODULE_DESCRIPTION("Fullhan WatchDog device driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig
index e38039fd..929c0bec 100644
--- a/fs/ext4/Kconfig
+++ b/fs/ext4/Kconfig
@@ -37,6 +37,7 @@ config EXT4_FS
select CRC16
select CRYPTO
select CRYPTO_CRC32C
+ select HALFMD4
help
This is the next generation of the ext3 filesystem.
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 88720011..21c43bb7 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -664,7 +664,7 @@ static void fat_set_state(struct super_block *sb,
if (sbi->dirty) {
/* warn only on set (mount). */
if (set)
- fat_msg(sb, KERN_WARNING, "Volume was not properly "
+ fat_msg(sb, KERN_NOTICE, "Volume was not properly "
"unmounted. Some data may be corrupt. "
"Please run fsck.");
return;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 8d3e4840..ecc3b121 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -117,6 +117,38 @@ static struct file_system_type proc_fs_type = {
.fs_flags = FS_USERNS_MOUNT,
};
+#ifdef CONFIG_DEFERRED_INIICALLS
+extern void do_deferred_initcalls(void);
+
+static ssize_t deferred_initcalls_read_proc(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ static int deferred_initcalls_done;
+ int len, ret;
+ char tmp[3] = "1\n";
+
+ if (*ppos >= 3)
+ return 0;
+
+ if ((!deferred_initcalls_done) && !(*ppos)) {
+ tmp[0] = '0';
+ do_deferred_initcalls();
+ deferred_initcalls_done = 1;
+ }
+
+ len = min_t(size_t, nbytes, (size_t)3);
+ ret = copy_to_user(buf, tmp, len);
+ if (ret)
+ return -EFAULT;
+ *ppos += len;
+ return len;
+}
+
+static const struct file_operations deferred_initcalls_fops = {
+ .read = deferred_initcalls_read_proc,
+};
+#endif
+
void __init proc_root_init(void)
{
int err;
@@ -128,6 +160,9 @@ void __init proc_root_init(void)
proc_self_init();
proc_thread_self_init();
+#ifdef CONFIG_DEFERRED_INIICALLS
+ proc_create("deferred_initcalls", 0644, NULL, &deferred_initcalls_fops);
+#endif
proc_symlink("mounts", NULL, "self/mounts");
proc_net_init();
@@ -167,6 +202,7 @@ static int proc_root_readdir(struct file *file, struct dir_context *ctx)
{
if (ctx->pos < FIRST_PROCESS_ENTRY) {
int error = proc_readdir(file, ctx);
+
if (unlikely(error <= 0))
return error;
ctx->pos = FIRST_PROCESS_ENTRY;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 0a4c2d4d..74ba3a27 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -730,6 +730,30 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
return 0;
}
+/*
+ * Used when setting automatic NUMA hinting protection where it is
+ * critical that a numa hinting PMD is not confused with a bad PMD.
+ */
+static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd)
+{
+ pmd_t pmdval = pmd_read_atomic(pmd);
+
+ /* See pmd_none_or_trans_hug_or_clear_bad for info on barrier */
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ barrier();
+#endif
+
+ if (pmd_none(pmdval))
+ return 1;
+ if (pmd_trans_huge(pmdval))
+ return 0;
+ if (unlikely(pmd_bad(pmdval))) {
+ pmd_clear_bad(pmd);
+ return 1;
+ }
+ return 0;
+}
+
/*
* This is a noop if Transparent Hugepage Support is not built into
* the kernel. Otherwise it is equivalent to
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 1462071a..8565cb92 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -40,7 +40,7 @@
* }
*
* [__init_begin, __init_end] is the init section that may be freed after init
- * // __init_begin and __init_end should be page aligned, so that we can
+ * // __init_begin and __init_end should be page aligned, so that we can
* // free the whole .init memory
* [_stext, _etext] is the text section
* [_sdata, _edata] is the data section
@@ -105,7 +105,7 @@
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
#define MCOUNT_REC() . = ALIGN(8); \
VMLINUX_SYMBOL(__start_mcount_loc) = .; \
- *(__mcount_loc) \
+ KEEP(*(__mcount_loc)) \
VMLINUX_SYMBOL(__stop_mcount_loc) = .;
#else
#define MCOUNT_REC()
@@ -113,7 +113,7 @@
#ifdef CONFIG_TRACE_BRANCH_PROFILING
#define LIKELY_PROFILE() VMLINUX_SYMBOL(__start_annotated_branch_profile) = .; \
- *(_ftrace_annotated_branch) \
+ KEEP(*(_ftrace_annotated_branch)) \
VMLINUX_SYMBOL(__stop_annotated_branch_profile) = .;
#else
#define LIKELY_PROFILE()
@@ -121,7 +121,7 @@
#ifdef CONFIG_PROFILE_ALL_BRANCHES
#define BRANCH_PROFILE() VMLINUX_SYMBOL(__start_branch_profile) = .; \
- *(_ftrace_branch) \
+ KEEP(*(_ftrace_branch)) \
VMLINUX_SYMBOL(__stop_branch_profile) = .;
#else
#define BRANCH_PROFILE()
@@ -130,7 +130,7 @@
#ifdef CONFIG_KPROBES
#define KPROBE_BLACKLIST() . = ALIGN(8); \
VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
- *(_kprobe_blacklist) \
+ KEEP(*(_kprobe_blacklist)) \
VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
#else
#define KPROBE_BLACKLIST()
@@ -139,10 +139,10 @@
#ifdef CONFIG_EVENT_TRACING
#define FTRACE_EVENTS() . = ALIGN(8); \
VMLINUX_SYMBOL(__start_ftrace_events) = .; \
- *(_ftrace_events) \
+ KEEP(*(_ftrace_events)) \
VMLINUX_SYMBOL(__stop_ftrace_events) = .; \
VMLINUX_SYMBOL(__start_ftrace_enum_maps) = .; \
- *(_ftrace_enum_map) \
+ KEEP(*(_ftrace_enum_map)) \
VMLINUX_SYMBOL(__stop_ftrace_enum_maps) = .;
#else
#define FTRACE_EVENTS()
@@ -150,10 +150,10 @@
#ifdef CONFIG_TRACING
#define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \
- *(__trace_printk_fmt) /* Trace_printk fmt' pointer */ \
+ KEEP(*(__trace_printk_fmt)) /* Trace_printk fmt' pointer */ \
VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .;
#define TRACEPOINT_STR() VMLINUX_SYMBOL(__start___tracepoint_str) = .; \
- *(__tracepoint_str) /* Trace_printk fmt' pointer */ \
+ KEEP(*(__tracepoint_str)) /* Trace_printk fmt' pointer */ \
VMLINUX_SYMBOL(__stop___tracepoint_str) = .;
#else
#define TRACE_PRINTKS()
@@ -163,7 +163,7 @@
#ifdef CONFIG_FTRACE_SYSCALLS
#define TRACE_SYSCALLS() . = ALIGN(8); \
VMLINUX_SYMBOL(__start_syscalls_metadata) = .; \
- *(__syscalls_metadata) \
+ KEEP(*(__syscalls_metadata)) \
VMLINUX_SYMBOL(__stop_syscalls_metadata) = .;
#else
#define TRACE_SYSCALLS()
@@ -172,7 +172,7 @@
#ifdef CONFIG_SERIAL_EARLYCON
#define EARLYCON_TABLE() . = ALIGN(8); \
VMLINUX_SYMBOL(__earlycon_table) = .; \
- *(__earlycon_table) \
+ KEEP(*(__earlycon_table)) \
VMLINUX_SYMBOL(__earlycon_table_end) = .;
#else
#define EARLYCON_TABLE()
@@ -185,7 +185,7 @@
#define _OF_TABLE_1(name) \
. = ALIGN(8); \
VMLINUX_SYMBOL(__##name##_of_table) = .; \
- *(__##name##_of_table) \
+ KEEP(*(__##name##_of_table)) \
*(__##name##_of_table_end)
#define CLKSRC_OF_TABLES() OF_TABLE(CONFIG_CLKSRC_OF, clksrc)
@@ -200,7 +200,7 @@
#define ACPI_PROBE_TABLE(name) \
. = ALIGN(8); \
VMLINUX_SYMBOL(__##name##_acpi_probe_table) = .; \
- *(__##name##_acpi_probe_table) \
+ KEEP(*(__##name##_acpi_probe_table)) \
VMLINUX_SYMBOL(__##name##_acpi_probe_table_end) = .;
#else
#define ACPI_PROBE_TABLE(name)
@@ -209,7 +209,7 @@
#define KERNEL_DTB() \
STRUCT_ALIGN(); \
VMLINUX_SYMBOL(__dtb_start) = .; \
- *(.dtb.init.rodata) \
+ KEEP(*(.dtb.init.rodata)) \
VMLINUX_SYMBOL(__dtb_end) = .;
/*
@@ -233,7 +233,7 @@
VMLINUX_SYMBOL(__start___verbose) = .; \
*(__verbose) \
VMLINUX_SYMBOL(__stop___verbose) = .; \
- LIKELY_PROFILE() \
+ LIKELY_PROFILE() \
BRANCH_PROFILE() \
TRACE_PRINTKS() \
TRACEPOINT_STR()
@@ -448,7 +448,6 @@
KEEP(*(.security_initcall.init)) \
VMLINUX_SYMBOL(__security_initcall_end) = .; \
}
-
/*
* .text section. Map to function alignment to avoid address changes
* during second ld run in second ld pass when generating System.map
@@ -520,7 +519,7 @@
#endif
/* Section used for early init (in .S files) */
-#define HEAD_TEXT *(.head.text)
+#define HEAD_TEXT KEEP(*(.head.text))
#define HEAD_TEXT_SECTION \
.head.text : AT(ADDR(.head.text) - LOAD_OFFSET) { \
@@ -565,7 +564,7 @@
MEM_DISCARD(init.data) \
KERNEL_CTORS() \
MCOUNT_REC() \
- *(.init.rodata) \
+ *(.init.rodata .init.rodata.*) \
FTRACE_EVENTS() \
TRACE_SYSCALLS() \
KPROBE_BLACKLIST() \
@@ -583,7 +582,7 @@
EARLYCON_TABLE()
#define INIT_TEXT \
- *(.init.text) \
+ *(.init.text .init.text.*) \
*(.text.startup) \
MEM_DISCARD(init.text)
@@ -600,7 +599,7 @@
MEM_DISCARD(exit.text)
#define EXIT_CALL \
- *(.exitcall.exit)
+ KEEP(*(.exitcall.exit))
/*
* bss (Block Started by Symbol) - uninitialized data
@@ -705,7 +704,7 @@
#define INIT_SETUP(initsetup_align) \
. = ALIGN(initsetup_align); \
VMLINUX_SYMBOL(__setup_start) = .; \
- *(.init.setup) \
+ KEEP(*(.init.setup)) \
VMLINUX_SYMBOL(__setup_end) = .;
#define INIT_CALLS_LEVEL(level) \
@@ -713,6 +712,15 @@
KEEP(*(.initcall##level##.init)) \
KEEP(*(.initcall##level##s.init)) \
+#ifdef CONFIG_DEFERRED_INIICALLS
+#define DEFERRED_INITCALLS \
+ VMLINUX_SYMBOL(__deferred_initcall_start) = .; \
+ KEEP(*(.deferred_initcall.init)) \
+ VMLINUX_SYMBOL(__deferred_initcall_end) = .;
+#else
+#define DEFERRED_INITCALLS
+#endif
+
#define INIT_CALLS \
VMLINUX_SYMBOL(__initcall_start) = .; \
KEEP(*(.initcallearly.init)) \
@@ -725,7 +733,8 @@
INIT_CALLS_LEVEL(rootfs) \
INIT_CALLS_LEVEL(6) \
INIT_CALLS_LEVEL(7) \
- VMLINUX_SYMBOL(__initcall_end) = .;
+ VMLINUX_SYMBOL(__initcall_end) = .; \
+ DEFERRED_INITCALLS
#define CON_INITCALL \
VMLINUX_SYMBOL(__con_initcall_start) = .; \
diff --git a/include/crypto/fullhan/config.h b/include/crypto/fullhan/config.h
new file mode 100644
index 00000000..e850ad93
--- /dev/null
+++ b/include/crypto/fullhan/config.h
@@ -0,0 +1,19 @@
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+
+
+/********* Here define the function supported by chip *****************/
+#define CIPHER_HASH_SUPPORT
+//#define CIPHER_MHASH_SUPPORT
+//#define CIPHER_RSA_SUPPORT
+//#define CIPHER_RNG_SUPPORT
+//#define CIPHER_RNG_VERSION_2
+//#define CIPHER_CCM_GCM_SUPPORT
+#define CIPHER_MULTICIPHER_SUPPORT
+//#define CIPHER_EFUSE_SUPPORT
+//#define CIPHER_KLAD_SUPPORT
+
+
+#endif
+
diff --git a/include/crypto/fullhan/drv_cipher_ioctl.h b/include/crypto/fullhan/drv_cipher_ioctl.h
new file mode 100644
index 00000000..cf35d516
--- /dev/null
+++ b/include/crypto/fullhan/drv_cipher_ioctl.h
@@ -0,0 +1,127 @@
+/******************************************************************************
+
+ Copyright (C), 2011-2014, Fullhan Tech. Co., Ltd.
+
+ ******************************************************************************
+ File Name : drv_cipher_ioctl.h
+ Version : Initial Draft
+ Author : Fullhan fhsecurity team
+ Created :
+ Last Modified :
+ Description :
+ Function List :
+ History :
+******************************************************************************/
+
+#ifndef __DRV_CIPHER_IOCTL_H__
+#define __DRV_CIPHER_IOCTL_H__
+
+#include "fh_type.h"
+#include "fh_unf_cipher.h"
+#include "fh_drv_cipher.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif /* __cplusplus */
+
+
+
+typedef struct _CMD_CIPHER_HANDLE_S {
+ FH_HANDLE hdlr;
+} CMD_CIPHER_CREATE_S, CMD_CIPHER_DESTROY_S, CMD_CIPHER_PROCESS_STOP_S;
+
+typedef struct _CMD_CIPHER_CTRL_S {
+ FH_HANDLE hdlr;
+ FH_UNF_CIPHER_CTRL_S ctrl;
+} CMD_CIPHER_CTRL_S, CMD_CIPHER_INFO_S;
+
+typedef struct _CMD_CIPHER_PROCESS_S {
+ FH_HANDLE hdlr;
+
+ FH_UNF_CIPHER_DATA_S *pKernelDataPkg;
+ FH_UNF_CIPHER_DATA_S *pDataPkg;
+ FH_U32 DataPkgNum;
+ FH_UNF_CIPHER_CTRL_S ctrl;
+} CMD_CIPHER_PROCESS_S;
+
+typedef struct _CMD_HASH_INIT_S {
+ FH_HANDLE hdlr;
+
+ FH_UNF_CIPHER_HASH_TYPE_E alg;
+ FH_U8 *hmackey;
+ FH_U8 *khmackey;
+} CMD_HASH_INIT_S;
+
+typedef struct _CMD_HASH_UPDATE_S {
+ FH_HANDLE hdlr;
+
+ FH_U8 *kmsg;
+ FH_U8 *msg;
+ FH_U32 msglen;
+} CMD_HASH_UPDATE_S;
+
+typedef struct _CMD_HASH_FINAL_S {
+ FH_HANDLE hdlr;
+
+ FH_U8 *output;
+} CMD_HASH_FINAL_S;
+
+typedef struct _CMD_HASH_DIGEST_S {
+ FH_UNF_CIPHER_HASH_TYPE_E alg;
+ FH_U32 u32MsgPhyAddr;
+ FH_U32 msglen;
+ FH_U8 *output;
+} CMD_HASH_DIGEST_S;
+
+typedef struct _CMD_GET_HASHINFO_S {
+ FH_HANDLE hdlr;
+ FH_UNF_CIPHER_HASH_TYPE_E *alg;
+ FH_UNF_CIPHER_HASH_TYPE_E kalg;
+ FH_U8 *hmackey;
+ FH_U8 *khmackey;
+} CMD_GET_HASHINFO_S;
+
+
+
+/* Ioctl definitions */
+#define FH_ID_CIPHER 100
+#define FH_ID_HASH 101
+
+#define CMD_CIPHER_CREATEHANDLE _IOWR(FH_ID_CIPHER, 0x1, CMD_CIPHER_CREATE_S)
+#define CMD_CIPHER_DESTROYHANDLE _IOW(FH_ID_CIPHER, 0x2, CMD_CIPHER_DESTROY_S)
+#define CMD_CIPHER_CONFIGHANDLE _IOW(FH_ID_CIPHER, 0x3, CMD_CIPHER_CTRL_S)
+#define CMD_CIPHER_ENCRYPT _IOW(FH_ID_CIPHER, 0x4, CMD_CIPHER_PROCESS_S)
+#define CMD_CIPHER_DECRYPT _IOW(FH_ID_CIPHER, 0x5, CMD_CIPHER_PROCESS_S)
+#define CMD_CIPHER_DECRYPTMULTI _IOW(FH_ID_CIPHER, 0x6, CMD_CIPHER_PROCESS_S)
+#define CMD_CIPHER_ENCRYPTMULTI _IOW(FH_ID_CIPHER, 0x7, CMD_CIPHER_PROCESS_S)
+#define CMD_CIPHER_GETHANDLECONFIG _IOWR(FH_ID_CIPHER, 0x9, CMD_CIPHER_CTRL_S)
+#define CMD_CIPHER_DECRYPTMULTI_EX _IOW(FH_ID_CIPHER, 0xe, CMD_CIPHER_PROCESS_S)
+#define CMD_CIPHER_ENCRYPTMULTI_EX _IOW(FH_ID_CIPHER, 0xf, CMD_CIPHER_PROCESS_S)
+
+#ifdef CIPHER_KLAD_SUPPORT
+#define CMD_CIPHER_KLAD_KEY _IOWR(FH_ID_CIPHER, 0x12, CIPHER_KLAD_KEY_S)
+#endif
+
+#ifdef CIPHER_RNG_SUPPORT
+#define CMD_CIPHER_GETRANDOMNUMBER _IOWR(FH_ID_CIPHER, 0x8, CIPHER_RNG_S)
+#endif
+
+#ifdef CIPHER_HASH_SUPPORT
+#define CMD_CIPHER_CALCHASHINIT _IOWR(FH_ID_CIPHER, 0xa, CMD_HASH_INIT_S)
+#define CMD_CIPHER_CALCHASHUPDATE _IOWR(FH_ID_CIPHER, 0xb, CMD_HASH_UPDATE_S)
+#define CMD_CIPHER_CALCHASHFINAL _IOWR(FH_ID_CIPHER, 0xc, CMD_HASH_FINAL_S)
+#define CMD_CIPHER_CALCHASH _IOWR(FH_ID_CIPHER, 0x10, CMD_HASH_DIGEST_S)
+#define CMD_CIPHER_GET_HASHINFO _IOWR(FH_ID_CIPHER, 0x11, CMD_GET_HASHINFO_S)
+#endif
+
+#ifdef CIPHER_RSA_SUPPORT
+#define CMD_CIPHER_CALCRSA _IOWR(FH_ID_CIPHER, 0xd, CIPHER_RSA_DATA_S)
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* End of #ifndef __DRV_CIPHER_IOCTL_H__*/
diff --git a/include/crypto/fullhan/fh_drv_cipher.h b/include/crypto/fullhan/fh_drv_cipher.h
new file mode 100644
index 00000000..f8480b58
--- /dev/null
+++ b/include/crypto/fullhan/fh_drv_cipher.h
@@ -0,0 +1,259 @@
+/******************************************************************************
+
+ Copyright (C), 2011-2014, Fullhan Tech. Co., Ltd.
+
+ ******************************************************************************
+ File Name :fh_drv_cipher.h
+ Version : Initial Draft
+ Author : Fullhan fhsecurity team
+ Created :
+ Last Modified :
+ Description :
+ Function List :
+ History :
+******************************************************************************/
+
+#ifndef __FH_DRV_CIPHER_H__
+#define __FH_DRV_CIPHER_H__
+
+#include "fh_type.h"
+#include "fh_unf_cipher.h"
+#include "config.h"
+
+#include <linux/mutex.h>
+#include <linux/completion.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+#define HASH_BLOCK_SIZE (64)
+
+#ifdef CIPHER_MULTICIPHER_SUPPORT
+#endif
+
+#ifdef CIPHER_HASH_SUPPORT
+#endif
+
+#ifdef CIPHER_RNG_SUPPORT
+typedef struct {
+ FH_U32 u32TimeOutUs;
+ FH_U32 u32RNG;
+}CIPHER_RNG_S;
+#endif
+
+#ifdef CIPHER_RSA_SUPPORT
+typedef struct {
+ FH_U8 *pu8Input;
+ FH_U8 *pu8Output;
+ FH_U32 u32DataLen;
+ FH_U8 *pu8N;
+ FH_U8 *pu8K;
+ FH_U16 u16NLen;
+ FH_U16 u16KLen;
+ FH_UNF_CIPHER_KEY_SRC_E enKeySrc;
+}CIPHER_RSA_DATA_S;
+
+typedef struct {
+ FH_UNF_CIPHER_RSA_PRI_KEY_S stPriKey;
+ FH_U32 u32NumBits;
+ FH_U32 u32Exponent;
+}CIPHER_RSA_KEY_S;
+#endif
+
+#ifdef CIPHER_KLAD_SUPPORT
+typedef struct {
+ FH_UNF_CIPHER_KEY_SRC_E enRootKey;
+ FH_UNF_CIPHER_KLAD_TARGET_E enTarget;
+ FH_U32 u32CleanKey[4];
+ FH_U32 u32EncryptKey[4];
+}CIPHER_KLAD_KEY_S;
+#endif
+
+#ifdef CIPHER_MULTICIPHER_SUPPORT
+FH_S32 FH_DRV_CIPHER_CreateHandle(FH_HANDLE *pHdlr, FH_VOID *p_priv);
+FH_S32 FH_DRV_CIPHER_DestroyHandle(FH_HANDLE Hdlr);
+FH_S32 FH_DRV_CIPHER_Config(FH_HANDLE Hdlr, FH_UNF_CIPHER_CTRL_S *pConfig);
+FH_S32 FH_DRV_CIPHER_Encrypt(FH_HANDLE Hdlr, FH_U32 ScrPhyAddr, FH_U32 DestPhyAddr, FH_U32 u32DataLength);
+FH_S32 FH_DRV_CIPHER_Decrypt(FH_HANDLE Hdlr, FH_U32 ScrPhyAddr, FH_U32 DestPhyAddr, FH_U32 u32DataLength);
+FH_S32 FH_DRV_CIPHER_EncryptMulti(FH_HANDLE Hdlr, FH_UNF_CIPHER_DATA_S *DataPkg, FH_U32 DataPkgNum);
+FH_S32 FH_DRV_CIPHER_DecryptMulti(FH_HANDLE Hdlr, FH_UNF_CIPHER_DATA_S *DataPkg, FH_U32 DataPkgNum);
+FH_S32 FH_DRV_CIPHER_GetHandleConfig(FH_HANDLE Hdlr, FH_UNF_CIPHER_CTRL_S *pConfig);
+#endif
+
+#ifdef CIPHER_RNG_SUPPORT
+FH_S32 FH_DRV_CIPHER_GetRandomNumber(CIPHER_RNG_S *pstRNG);
+#endif
+
+#ifdef CIPHER_HASH_SUPPORT
+FH_S32 FH_DRV_CIPHER_CalcHashInit(FH_HANDLE *pHdlr, FH_VOID *p_priv, FH_UNF_CIPHER_HASH_TYPE_E alg, FH_U8 *hmackey);
+FH_S32 FH_DRV_CIPHER_CalcHashUpdate(FH_HANDLE Hdlr, FH_U8 *msg, FH_U32 msglen);
+FH_S32 FH_DRV_CIPHER_CalcHashFinal(FH_HANDLE Hdlr, FH_U8 *dgst, FH_U32 *dgstlen);
+FH_S32 FH_DRV_CIPHER_CalcHash(FH_VOID *p_priv,
+ FH_UNF_CIPHER_HASH_TYPE_E alg,
+ FH_U32 MsgPhyAddr,
+ FH_U32 MsgLen,
+ FH_U8 *dgst,
+ FH_U32 *dgstlen);
+FH_S32 FH_DRV_CIPHER_GetHashInfo(FH_HANDLE Hdlr, FH_UNF_CIPHER_HASH_TYPE_E *alg, FH_U8 **hmackey);
+#endif
+
+#ifdef CIPHER_RSA_SUPPORT
+FH_S32 FH_DRV_CIPHER_CalcRsa(CIPHER_RSA_DATA_S *pCipherRsaData);
+#endif
+
+#ifdef CIPHER_KLAD_SUPPORT
+FH_S32 FH_DRV_CIPHER_KladEncryptKey(CIPHER_KLAD_KEY_S *pstKladKey);
+#endif
+
+FH_VOID FH_DRV_CIPHER_Suspend(FH_VOID);
+FH_S32 FH_DRV_CIPHER_Resume(FH_VOID);
+FH_S32 FH_DRV_CIPHER_SoftReset(FH_VOID);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef enum {
+ RPU_ALGO_AES128,
+ RPU_ALGO_DES,
+ RPU_ALGO_TDES,
+ RPU_ALGO_SM4,
+ RPU_ALGO_SHA1,
+ RPU_ALGO_SHA256,
+ RPU_ALGO_SM3,
+ RPU_ALGO_RSA2048_SIGN,
+ RPU_ALGO_RSA2048_VERIFY,
+ RPU_ALGO_SM2_SIGN,
+ RPU_ALGO_SM2_VERIFY,
+} DRV_RPU_ALGO_E;
+
+typedef enum _DRV_RPU_ST_E {
+ RPU_ST_AES128_SH256_RSA2048_4_AES128 = 0x1,
+ RPU_ST_AES128_SH256_RSA2048_4_SH256 = 0x2,
+ RPU_ST_AES128_SH256_RSA2048_4_RSA2048 = 0x3,
+
+ RPU_ST_SM2_SM3_SM4_4_SM4 = 0x04,
+ RPU_ST_SM2_SM3_SM4_4_SM3 = 0x08,
+ RPU_ST_SM2_SM3_SM4_4_SM2_VERIFY = 0x0C,
+ RPU_ST_SM2_SM3_SM4_4_SM2_SIGN = 0x10,
+
+ RPU_ST_DES = 0x20,
+ RPU_ST_TDES = 0x40,
+ RPU_ST_SH1 = 0x60,
+
+ RPU_ST_BUTT = 0,
+} DRV_RPU_ST_E;
+
+typedef enum _DRV_RPU_STAGE_E {
+ RPU_STAGE_CREATE,
+ RPU_STAGE_CONFIG,
+ RPU_STAGE_DATA,
+ RPU_STAGE_BUTT,
+} DRV_RPU_STAGE_E;
+
+typedef struct _DRV_CIPHER_HDLR_S {
+ void *priv;
+ void __iomem *regs;
+
+ DRV_RPU_ST_E st;
+ bool is_break;
+ DRV_RPU_STAGE_E stage;
+ bool is_init;
+
+ FH_U32 IVSet;
+ FH_U32 iv[4];
+ FH_U32 key[8];
+ FH_U32 iv_len;
+ FH_U32 key_len;
+ FH_U32 work_mode;
+ DRV_RPU_ALGO_E algo;
+} DRV_CIPHER_HDLR_S;
+
+typedef enum _DRV_HASH_STAGE_E {
+ HASH_STAGE_INIT,
+ HASH_STAGE_UPDATE,
+ HASH_STAGE_FINAL,
+ HASH_STAGE_BUTT,
+} DRV_HASH_STAGE_E;
+
+typedef struct _DRV_HASH_HDLR_S {
+#if 0
+ void *priv;
+ void __iomem *regs;
+
+ DRV_RPU_ST_E st;
+ bool is_break;
+ DRV_HASH_STAGE_E stage;
+ bool is_init;
+
+ FH_U32 state[8];
+ DRV_RPU_ALGO_E algo;
+
+ FH_U32 remain[HASH_BLOCK_SIZE/2];
+ FH_U32 remain_len;
+ FH_U32 total_len;
+
+ FH_U8 hmackey[HASH_BLOCK_SIZE];
+ bool is_hmac;
+#else
+ void *priv;
+ void __iomem *regs;
+
+ FH_U32 state[8];
+ FH_U32 remain[HASH_BLOCK_SIZE/2];
+ FH_U32 remain_len;
+ FH_U32 total_len;
+
+ DRV_RPU_ALGO_E algo;
+ DRV_RPU_ST_E st;
+ DRV_HASH_STAGE_E stage;
+ bool is_break;
+ bool is_init;
+ bool is_hmac;
+ FH_U8 hmackey[HASH_BLOCK_SIZE];
+#endif
+} DRV_HASH_HDLR_S;
+
+typedef struct fhCESA_RES_S {
+ struct device *dev;
+ void __iomem *regs;
+ int irq;
+ struct clk *clk;
+ struct completion completion;
+ struct mutex lock;
+ /* spinlock_t lock; */
+
+ DRV_RPU_ST_E st;
+ void *curr_hdlr;
+}CESA_RES_S;
+
+DRV_RPU_ST_E rpu_st_switch(void __iomem *regbase, DRV_RPU_ST_E old, DRV_RPU_ST_E new);
+
+
+
+
+
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* End of #ifndef __FH_DRV_CIPHER_H__*/
+
diff --git a/include/crypto/fullhan/fh_error_mpi.h b/include/crypto/fullhan/fh_error_mpi.h
new file mode 100644
index 00000000..f4728f9c
--- /dev/null
+++ b/include/crypto/fullhan/fh_error_mpi.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+
+ Copyright (C), 2001-2014, Fullhan Tech. Co., Ltd.
+
+ ******************************************************************************
+ File Name : fh_error_mpi.h
+ Version : Initial Draft
+ Author : Fullhan multimedia software group
+ Created : 2008/04/24
+ Description : error code of MPI
+ History :
+ 1.Date : 2008/04/24
+ Author : q46153
+ Modification: Created file
+
+******************************************************************************/
+/**
+\file
+\brief Describes the information about common error codes.
+*/
+/* add include here */
+#ifndef __FH_UNF_MPI_ERRORCODE_H__
+#define __FH_UNF_MPI_ERRORCODE_H__
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C"
+{
+#endif
+#endif /* End of #ifdef __cplusplus */
+
+/***************************** Macro Definition ******************************/
+/** \addtogroup MSP_ERRCODE */
+/** @{ */ /** <!-- [MSP_ERRCODE] */
+
+#define FH_ERR_CIPHER_NOT_INIT (FH_S32)(0x804D0001)
+#define FH_ERR_CIPHER_INVALID_HANDLE (FH_S32)(0x804D0002)
+#define FH_ERR_CIPHER_INVALID_POINT (FH_S32)(0x804D0003)
+#define FH_ERR_CIPHER_INVALID_PARA (FH_S32)(0x804D0004)
+#define FH_ERR_CIPHER_FAILED_INIT (FH_S32)(0x804D0005)
+#define FH_ERR_CIPHER_FAILED_GETHANDLE (FH_S32)(0x804D0006)
+#define FH_ERR_CIPHER_FAILED_RELEASEHANDLE (FH_S32)(0x804D0007)
+#define FH_ERR_CIPHER_FAILED_CONFIGAES (FH_S32)(0x804D0008)
+#define FH_ERR_CIPHER_FAILED_CONFIGDES (FH_S32)(0x804D0009)
+#define FH_ERR_CIPHER_FAILED_ENCRYPT (FH_S32)(0x804D000A)
+#define FH_ERR_CIPHER_FAILED_DECRYPT (FH_S32)(0x804D000B)
+#define FH_ERR_CIPHER_BUSY (FH_S32)(0x804D000C)
+#define FH_ERR_CIPHER_NO_AVAILABLE_RNG (FH_S32)(0x804D000D)
+
+#define FH_ERR_CIPHER_FAILED_CONFIGKEY (FH_S32)(0x804D000E)
+#define FH_ERR_CIPHER_FAILED_CONFIGIV (FH_S32)(0x804D000F)
+#define FH_ERR_CIPHER_FAILED_CONFIGINS (FH_S32)(0x804D0010)
+#define FH_ERR_CIPHER_FAILED_CHECKSTAGE (FH_S32)(0x804D0011)
+#define FH_ERR_CIPHER_FAILED_CHECKST (FH_S32)(0x804D0012)
+#define FH_ERR_CIPHER_FAILED_CHECKALG (FH_S32)(0x804D0013)
+
+/** @} */ /*! <!-- Macro Definition end */
+
+
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* End of #ifdef __cplusplus */
+
+
+#endif /* End of #ifndef __FH_UNF_MPI_ERRORCODE_H__ */
+
diff --git a/include/crypto/fullhan/fh_type.h b/include/crypto/fullhan/fh_type.h
new file mode 100644
index 00000000..1b6856f0
--- /dev/null
+++ b/include/crypto/fullhan/fh_type.h
@@ -0,0 +1,134 @@
+/******************************************************************************
+ Copyright (C), 2001-2011, Fullhan Tech. Co., Ltd.
+******************************************************************************
+File Name : fh_type.h
+Version : Initial Draft
+Author : Fullhan multimedia software group
+Created : 2005/4/23
+Last Modified :
+Description : Common data types of the system.
+Function List :
+History :
+******************************************************************************/
+#ifndef __FH_TYPE_H__
+#define __FH_TYPE_H__
+
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C"{
+#endif
+#endif /* __cplusplus */
+
+/* #include "types/type_def.h" */
+/*--------------------------------------------------------------------------------------------------------------*
+ * Defintion of basic data types. The data types are applicable to both the application layer and kernel codes. *
+ *--------------------------------------------------------------------------------------------------------------*/
+/*************************** Structure Definition ****************************/
+/** \addtogroup Common_TYPE */
+/** @{ */ /** <!-- [Common_TYPE] */
+
+typedef unsigned char FH_U8;
+typedef unsigned char FH_UCHAR;
+typedef unsigned short FH_U16;
+typedef unsigned int FH_U32;
+
+typedef char FH_S8;
+typedef short FH_S16;
+typedef int FH_S32;
+
+#ifndef _M_IX86
+typedef unsigned long long FH_U64;
+typedef long long FH_S64;
+#else
+typedef __int64 FH_U64;
+typedef __int64 FH_S64;
+#endif
+
+typedef char FH_CHAR;
+typedef char* FH_PCHAR;
+
+typedef float FH_FLOAT;
+typedef double FH_DOUBLE;
+typedef void FH_VOID;
+
+typedef unsigned long FH_SIZE_T;
+typedef unsigned long FH_LENGTH_T;
+
+typedef FH_U32 FH_HANDLE;
+
+typedef FH_U32 FH_PHYS_ADDR_T;
+typedef FH_U32 FH_VIRT_ADDR_T;
+/*----------------------------------------------*
+ * Constant Definition *
+ *----------------------------------------------*/
+typedef enum {
+ FH_FALSE = 0,
+ FH_TRUE = 1,
+} FH_BOOL;
+
+#ifndef NULL
+#define NULL 0L
+#endif
+#define FH_NULL 0L
+#define FH_NULL_PTR 0L
+
+#define FH_SUCCESS 0
+#define FH_FAILURE (-1)
+
+#define FH_INVALID_HANDLE (0xffffffff)
+
+#define FH_INVALID_PTS (0xffffffff)
+#define FH_INVALID_TIME (0xffffffff)
+
+#define FH_OS_LINUX 0xabcd
+#define FH_OS_WIN32 0xcdef
+
+#ifdef _WIN32
+#define FH_OS_TYPE FH_OS_WIN32
+#else
+#define __OS_LINUX__
+#define FH_OS_TYPE FH_OS_LINUX
+#endif
+
+#ifdef ADVCA_SUPPORT
+#define __INIT__
+#define __EXIT__
+#else
+#define __INIT__ __init
+#define __EXIT__ __exit
+#endif
+
+/**
+
+define of FH_HANDLE :
+bit31 bit0
+ |<---- 16bit --------->|<--- 8bit --->|<--- 8bit --->|
+ |--------------------------------------------------------------|
+ | FH_MOD_ID_E | mod defined data | chnID |
+ |--------------------------------------------------------------|
+
+mod defined data: private data define by each module(for example: sub-mod id), usually, set to 0.
+*/
+
+#define FH_HANDLE_MAKEHANDLE(mod, privatedata, chnid) (FH_HANDLE)( (((mod)& 0xffff) << 16) | ((((privatedata)& 0xff) << 8) ) | (((chnid) & 0xff)) )
+
+#define FH_HANDLE_GET_MODID(handle) (((handle) >> 16) & 0xffff)
+#define FH_HANDLE_GET_PriDATA(handle) (((handle) >> 8) & 0xff)
+#define FH_HANDLE_GET_CHNID(handle) (((handle)) & 0xff)
+
+
+#define UNUSED(x) ((x)=(x))
+
+
+
+/** @} */ /** <!-- ==== Structure Definition end ==== */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif /* __FH_TYPE_H__ */
+
diff --git a/include/crypto/fullhan/fh_unf_cipher.h b/include/crypto/fullhan/fh_unf_cipher.h
new file mode 100644
index 00000000..1e947c02
--- /dev/null
+++ b/include/crypto/fullhan/fh_unf_cipher.h
@@ -0,0 +1,735 @@
+#ifndef __FH_UNF_CIPHER_H__
+#define __FH_UNF_CIPHER_H__
+
+#include "fh_type.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+/*************************** Structure Definition ****************************/
+/** \addtogroup CIPHER */
+/** @{ */ /** <!-- [CIPHER] */
+
+/** min length of encrypt, unit: byte */
+#define FH_UNF_CIPHER_MIN_CRYPT_LEN 1
+
+/** max length of encrypt, unit: byte */
+#define FH_UNF_CIPHER_MAX_CRYPT_LEN 0xfffff
+
+#define FH_UNF_CIPHER_MAX_RSA_KEY_LEN (512)
+
+/** Cipher work mode */
+typedef enum fhFH_UNF_CIPHER_WORK_MODE_E
+{
+ FH_UNF_CIPHER_WORK_MODE_ECB, /**<Electronic codebook (ECB) mode*/
+ FH_UNF_CIPHER_WORK_MODE_CBC, /**<Cipher block chaining (CBC) mode*/
+ FH_UNF_CIPHER_WORK_MODE_CFB, /**<Cipher feedback (CFB) mode*/
+ FH_UNF_CIPHER_WORK_MODE_OFB, /**<Output feedback (OFB) mode*/
+ FH_UNF_CIPHER_WORK_MODE_CTR, /**<Counter (CTR) mode*/
+ FH_UNF_CIPHER_WORK_MODE_CCM,
+ FH_UNF_CIPHER_WORK_MODE_GCM,
+ FH_UNF_CIPHER_WORK_MODE_CBC_CTS, /**<Cipher block chaining CipherStealing mode*/
+ FH_UNF_CIPHER_WORK_MODE_BUTT = 0xffffffff
+}FH_UNF_CIPHER_WORK_MODE_E;
+
+/** Cipher algorithm */
+typedef enum fhFH_UNF_CIPHER_ALG_E
+{
+ FH_UNF_CIPHER_ALG_DES = 0x0, /**< Data encryption standard (DES) algorithm */
+ FH_UNF_CIPHER_ALG_3DES = 0x1, /**< 3DES algorithm */
+ FH_UNF_CIPHER_ALG_AES = 0x2, /**< Advanced encryption standard (AES) algorithm */
+ FH_UNF_CIPHER_ALG_SM4 = 0x3,
+ FH_UNF_CIPHER_ALG_BUTT = 0x4
+}FH_UNF_CIPHER_ALG_E;
+
+/** Key length */
+typedef enum fhFH_UNF_CIPHER_KEY_LENGTH_E
+{
+ FH_UNF_CIPHER_KEY_AES_128BIT = 0x0, /**< 128-bit key for the AES algorithm */
+ FH_UNF_CIPHER_KEY_AES_192BIT = 0x1, /**< 192-bit key for the AES algorithm */
+ FH_UNF_CIPHER_KEY_AES_256BIT = 0x2, /**< 256-bit key for the AES algorithm */
+ FH_UNF_CIPHER_KEY_DES_64BIT = 0x3, /**< 64-bit key for the DES algorithm */
+ FH_UNF_CIPHER_KEY_DES_128BIT = 0x4, /**< 128-bit key for the 3DES(ABA) algorithm */
+ FH_UNF_CIPHER_KEY_DES_192BIT = 0x5, /**< 192-bit key for the 3DES(ABC) algorithm */
+ FH_UNF_CIPHER_KEY_SM4_128BIT = 0x6, /**< 128-bit key for the SM4 algorithm */
+ FH_UNF_CIPHER_KEY_BUTT,
+}FH_UNF_CIPHER_KEY_LENGTH_E;
+
+/** Cipher bit width */
+typedef enum fhFH_UNF_CIPHER_BIT_WIDTH_E
+{
+ FH_UNF_CIPHER_BIT_WIDTH_64BIT = 0x0, /**< 64-bit width */
+ FH_UNF_CIPHER_BIT_WIDTH_8BIT = 0x1, /**< 8-bit width */
+ FH_UNF_CIPHER_BIT_WIDTH_1BIT = 0x2, /**< 1-bit width */
+ FH_UNF_CIPHER_BIT_WIDTH_128BIT = 0x3, /**< 128-bit width */
+}FH_UNF_CIPHER_BIT_WIDTH_E;
+
+/** Cipher control parameters */
+typedef struct fhFH_UNF_CIPHER_CTRL_CHANGE_FLAG_S
+{
+ FH_U32 bit1IV:1; /**< Initial Vector change or not */
+ FH_U32 bitsResv:31; /**< Reserved */
+}FH_UNF_CIPHER_CTRL_CHANGE_FLAG_S;
+
+/** Encryption/Decryption type selecting */
+typedef enum fhFH_UNF_CIPHER_KEY_SRC_E
+{
+ FH_UNF_CIPHER_KEY_SRC_USER = 0x0, /**< User Key*/
+ FH_UNF_CIPHER_KEY_SRC_EFUSE_0, /**< Efuse Key 0*/
+ FH_UNF_CIPHER_KEY_SRC_EFUSE_1, /**< Efuse Key 1*/
+ FH_UNF_CIPHER_KEY_SRC_EFUSE_2, /**< Efuse Key 2*/
+ FH_UNF_CIPHER_KEY_SRC_EFUSE_3, /**< Efuse Key 3*/
+ FH_UNF_CIPHER_KEY_SRC_KLAD_1, /**< KLAD Key 1*/
+ FH_UNF_CIPHER_KEY_SRC_KLAD_2, /**< KLAD Key 2*/
+ FH_UNF_CIPHER_KEY_SRC_KLAD_3, /**< KLAD Key 3*/
+ FH_UNF_CIPHER_KEY_SRC_BUTT,
+}FH_UNF_CIPHER_KEY_SRC_E;
+
+/** Encryption/Decryption type selecting */
+typedef enum
+{
+ FH_UNF_CIPHER_KLAD_TARGET_AES = 0x0, /**< Klad for AES*/
+ FH_UNF_CIPHER_KLAD_TARGET_RSA, /**< Klad for RSA*/
+ FH_UNF_CIPHER_KLAD_TARGET_BUTT,
+}FH_UNF_CIPHER_KLAD_TARGET_E;
+
+typedef struct fhUNF_CIPHER_CCM_INFO_S
+{
+ FH_U8 u8Nonce[16];
+ FH_U8 *pu8Aad;
+ FH_U32 u32ALen;
+ FH_U32 u32MLen;
+ FH_U8 u8NLen;
+ FH_U8 u8TLen;
+ FH_U8 u8Reserve[2];
+}FH_UNF_CIPHER_CCM_INFO_S;
+
+typedef struct fhUNF_CIPHER_GCM_INFO_S
+{
+ FH_U8 *pu8Aad;
+ FH_U32 u32ALen;
+ FH_U32 u32MLen;
+ FH_U32 u32IVLen;
+}FH_UNF_CIPHER_GCM_INFO_S;
+
+/** Structure of the cipher control information */
+typedef struct fhFH_UNF_CIPHER_CTRL_S
+{
+ FH_U32 u32Key[8]; /**< Key input */
+ FH_U32 u32IV[4]; /**< Initialization vector (IV) */
+ FH_UNF_CIPHER_ALG_E enAlg; /**< Cipher algorithm */
+ FH_UNF_CIPHER_BIT_WIDTH_E enBitWidth; /**< Bit width for cfb ofb encryption or decryption */
+ FH_UNF_CIPHER_WORK_MODE_E enWorkMode; /**< Operating mode */
+ FH_UNF_CIPHER_KEY_LENGTH_E enKeyLen; /**< Key length */
+ FH_UNF_CIPHER_CTRL_CHANGE_FLAG_S stChangeFlags; /**< control information exchange choices, we default all woulde be change except they have been in the choices */
+ FH_UNF_CIPHER_KEY_SRC_E enKeySrc; /**< Key source */
+#ifdef CIPHER_CCM_GCM_SUPPORT
+ union
+ {
+ FH_UNF_CIPHER_CCM_INFO_S stCCM;
+ FH_UNF_CIPHER_GCM_INFO_S stGCM;
+ }unModeInfo;
+#endif
+} FH_UNF_CIPHER_CTRL_S;
+
+/** Cipher data */
+typedef struct fhFH_UNF_CIPHER_DATA_S
+{
+ FH_U32 u32SrcPhyAddr; /**< phy address of the original data */
+ FH_U32 u32DestPhyAddr; /**< phy address of the purpose data */
+ FH_U32 u32ByteLength; /**< cigher data length*/
+} FH_UNF_CIPHER_DATA_S;
+
+/** Hash algrithm type */
+typedef enum fhFH_UNF_CIPHER_HASH_TYPE_E
+{
+ FH_UNF_CIPHER_HASH_TYPE_SHA1,
+ FH_UNF_CIPHER_HASH_TYPE_SHA256,
+ FH_UNF_CIPHER_HASH_TYPE_SM3,
+ FH_UNF_CIPHER_HASH_TYPE_HMAC_SHA1,
+ FH_UNF_CIPHER_HASH_TYPE_HMAC_SHA256,
+ FH_UNF_CIPHER_HASH_TYPE_HMAC_SM3,
+ FH_UNF_CIPHER_HASH_TYPE_BUTT,
+}FH_UNF_CIPHER_HASH_TYPE_E;
+
+/** Hash init struct input */
+typedef struct
+{
+ FH_U8 *pu8HMACKey;
+ FH_U32 u32HMACKeyLen;
+ FH_UNF_CIPHER_HASH_TYPE_E eShaType;
+}FH_UNF_CIPHER_HASH_ATTS_S;
+
+/** RSA encryption scheme*/
+typedef enum fhFH_UNF_CIPHER_RSA_ENC_SCHEME_E
+{
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_NO_PADDING, /**< without padding */
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_BLOCK_TYPE_0, /**< PKCS#1 block type 0 padding*/
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_BLOCK_TYPE_1, /**< PKCS#1 block type 1 padding*/
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_BLOCK_TYPE_2, /**< PKCS#1 block type 2 padding*/
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_OAEP_SHA1, /**< PKCS#1 RSAES-OAEP-SHA1 padding*/
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_OAEP_SHA256,/**< PKCS#1 RSAES-OAEP-SHA256 padding*/
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_PKCS1_V1_5, /**< PKCS#1 RSAES-PKCS1_V1_5 padding*/
+ FH_UNF_CIPHER_RSA_SCHEME_BUTT,
+}FH_UNF_CIPHER_RSA_ENC_SCHEME_E;
+
+/** RSA signature algorithms*/
+typedef enum fhFH_UNF_CIPHER_RSA_SIGN_SCHEME_E
+{
+ FH_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA1 = 0x100, /**< PKCS#1 RSASSA_PKCS1_V15_SHA1 signature*/
+ FH_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA256, /**< PKCS#1 RSASSA_PKCS1_V15_SHA256 signature*/
+ FH_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_PSS_SHA1, /**< PKCS#1 RSASSA_PKCS1_PSS_SHA1 signature*/
+ FH_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_PSS_SHA256, /**< PKCS#1 RSASSA_PKCS1_PSS_SHA256 signature*/
+ FH_UNF_CIPHER_RSA_SIGN_SCHEME_BUTT,
+}FH_UNF_CIPHER_RSA_SIGN_SCHEME_E;
+
+/** RSA public key struct */
+typedef struct
+{
+ FH_U8 *pu8N; /**< point to public modulus */
+ FH_U8 *pu8E; /**< point to public exponent */
+ FH_U16 u16NLen; /**< length of public modulus */
+ FH_U16 u16ELen; /**< length of public exponent */
+}FH_UNF_CIPHER_RSA_PUB_KEY_S;
+
+/** RSA private key struct */
+typedef struct
+{
+ FH_U8 *pu8N; /*!< public modulus */
+ FH_U8 *pu8E; /*!< public exponent */
+ FH_U8 *pu8D; /*!< private exponent */
+ FH_U8 *pu8P; /*!< 1st prime factor */
+ FH_U8 *pu8Q; /*!< 2nd prime factor */
+ FH_U8 *pu8DP; /*!< D % (P - 1) */
+ FH_U8 *pu8DQ; /*!< D % (Q - 1) */
+ FH_U8 *pu8QP; /*!< 1 / (Q % P) */
+ FH_U16 u16NLen; /**< length of public modulus */
+ FH_U16 u16ELen; /**< length of public exponent */
+ FH_U16 u16DLen; /**< length of private exponent */
+ FH_U16 u16PLen; /**< length of 1st prime factor */
+ FH_U16 u16QLen; /**< length of 2nd prime factor */
+ FH_U16 u16DPLen; /**< length of D % (P - 1) */
+ FH_U16 u16DQLen; /**< length of D % (Q - 1) */
+ FH_U16 u16QPLen; /**< length of 1 / (Q % P) */
+}FH_UNF_CIPHER_RSA_PRI_KEY_S;
+
+/** RSA public key encryption struct input */
+typedef struct
+{
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_E enScheme; /** RSA encryption scheme*/
+ FH_UNF_CIPHER_RSA_PUB_KEY_S stPubKey; /** RSA private key struct */
+}FH_UNF_CIPHER_RSA_PUB_ENC_S;
+
+/** RSA private key decryption struct input */
+typedef struct
+{
+ FH_UNF_CIPHER_RSA_ENC_SCHEME_E enScheme; /** RSA encryption scheme */
+ FH_UNF_CIPHER_RSA_PRI_KEY_S stPriKey; /** RSA public key struct */
+ FH_UNF_CIPHER_KEY_SRC_E enKeySrc;
+}FH_UNF_CIPHER_RSA_PRI_ENC_S;
+
+/** RSA signature struct input */
+typedef struct
+{
+ FH_UNF_CIPHER_RSA_SIGN_SCHEME_E enScheme; /** RSA signature scheme*/
+ FH_UNF_CIPHER_RSA_PRI_KEY_S stPriKey; /** RSA private key struct */
+ FH_UNF_CIPHER_KEY_SRC_E enKeySrc;
+ }FH_UNF_CIPHER_RSA_SIGN_S;
+
+/** RSA signature verify struct input */
+typedef struct
+{
+ FH_UNF_CIPHER_RSA_SIGN_SCHEME_E enScheme; /** RSA signature scheme*/
+ FH_UNF_CIPHER_RSA_PUB_KEY_S stPubKey; /** RSA public key struct */
+ }FH_UNF_CIPHER_RSA_VERIFY_S;
+
+/** @} */ /** <!-- ==== Structure Definition End ==== */
+
+
+#define FH_UNF_CIPHER_Open(FH_VOID) FH_UNF_CIPHER_Init(FH_VOID);
+#define FH_UNF_CIPHER_Close(FH_VOID) FH_UNF_CIPHER_DeInit(FH_VOID);
+
+/******************************* API Declaration *****************************/
+/** \addtogroup CIPHER */
+/** @{ */ /** <!-- [CIPHER] */
+/* ---CIPHER---*/
+/**
+\brief Init the cipher device.
+\attention \n
+This API is used to start the cipher device.
+\param N/A
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_FAILED_INIT The cipher device fails to be initialized.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_Init(FH_VOID);
+
+/**
+\brief Deinit the cipher device.
+\attention \n
+This API is used to stop the cipher device. If this API is called repeatedly, FH_SUCCESS is returned, but only the first operation takes effect.
+
+\param N/A
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT The cipher device is not initialized.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_DeInit(FH_VOID);
+
+/**
+\brief Obtain a cipher handle for encryption and decryption.
+
+\param[in] cipher attributes
+\param[out] phCipher Cipher handle
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT The cipher device is not initialized.
+\retval ::FH_ERR_CIPHER_INVALID_POINT The pointer is null.
+\retval ::FH_ERR_CIPHER_FAILED_GETHANDLE The cipher handle fails to be obtained, because there are no available cipher handles.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_CreateHandle(FH_HANDLE* phCipher);
+
+/**
+\brief Destroy the existing cipher handle.
+\attention \n
+This API is used to destroy existing cipher handles.
+
+\param[in] hCipher Cipher handle
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT The cipher device is not initialized.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_DestroyHandle(FH_HANDLE hCipher);
+
+/**
+\brief Get the random number.
+
+\attention \n
+This API is used to obtain the random number from the hardware.
+
+\param[out] pu32RandomNumber Point to the random number.
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_GetRandomNumber(FH_U32 *pu32RandomNumber);
+
+/**
+\brief Configures the cipher control information.
+\attention \n
+Before encryption or decryption, you must call this API to configure the cipher control information.
+The first 64-bit data and the last 64-bit data should not be the same when using TDES algorithm.
+
+\param[in] hCipher Cipher handle.
+\param[in] pstCtrl Cipher control information.
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT The cipher device is not initialized.
+\retval ::FH_ERR_CIPHER_INVALID_POINT The pointer is null.
+\retval ::FH_ERR_CIPHER_INVALID_PARA The parameter is invalid.
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE The handle is invalid.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_ConfigHandle(FH_HANDLE hCipher, FH_UNF_CIPHER_CTRL_S* pstCtrl);
+
+/**
+\brief Performs encryption.
+
+\attention \n
+This API is used to perform encryption by using the cipher module.
+The length of the encrypted data should be a multiple of 8 in TDES mode and 16 in AES mode. Besides, the length can not be bigger than 0xFFFFF.After this operation, the result will affect next operation.If you want to remove vector, you need to config IV(config pstCtrl->stChangeFlags.bit1IV with 1) by transfering FH_UNF_CIPHER_ConfigHandle.
+\param[in] hCipher Cipher handle
+\param[in] u32SrcPhyAddr Physical address of the source data
+\param[in] u32DestPhyAddr Physical address of the target data
+\param[in] u32ByteLength Length of the encrypted data
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT The cipher device is not initialized.
+\retval ::FH_ERR_CIPHER_INVALID_PARA The parameter is invalid.
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE The handle is invalid.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_Encrypt(FH_HANDLE hCipher, FH_U32 u32SrcPhyAddr, FH_U32 u32DestPhyAddr, FH_U32 u32ByteLength);
+
+/**
+\brief Performs decryption.
+
+\attention \n
+This API is used to perform decryption by using the cipher module.
+The length of the decrypted data should be a multiple of 8 in TDES mode and 16 in AES mode. Besides, the length can not be bigger than 0xFFFFF.After this operation, the result will affect next operation.If you want to remove vector, you need to config IV(config pstCtrl->stChangeFlags.bit1IV with 1) by transfering FH_UNF_CIPHER_ConfigHandle.
+\param[in] hCipher Cipher handle.
+\param[in] u32SrcPhyAddr Physical address of the source data.
+\param[in] u32DestPhyAddr Physical address of the target data.
+\param[in] u32ByteLength Length of the decrypted data
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT The cipher device is not initialized.
+\retval ::FH_ERR_CIPHER_INVALID_PARA The parameter is invalid.
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE The handle is invalid.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_Decrypt(FH_HANDLE hCipher, FH_U32 u32SrcPhyAddr, FH_U32 u32DestPhyAddr, FH_U32 u32ByteLength);
+
+/**
+\brief Encrypt multiple packaged data.
+\attention \n
+You can not encrypt more than 128 data package one time. When FH_ERR_CIPHER_BUSY return, the data package you send will not be deal, the custmer should decrease the number of data package or run cipher again.Note:When encrypting more than one packaged data, every one package will be calculated using initial vector configured by FH_UNF_CIPHER_ConfigHandle.Previous result will not affect the later result.
+\param[in] hCipher cipher handle
+\param[in] pstDataPkg data package ready for cipher
+\param[in] u32DataPkgNum number of package ready for cipher
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT cipher device have not been initialized
+\retval ::FH_ERR_CIPHER_INVALID_PARA parameter error
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE handle invalid
+\retval ::FH_ERR_CIPHER_BUSY hardware is busy, it can not deal with all data package once time
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_EncryptMulti(FH_HANDLE hCipher, FH_UNF_CIPHER_DATA_S *pstDataPkg, FH_U32 u32DataPkgNum);
+
+
+/**
+\brief Decrypt multiple packaged data.
+\attention \n
+You can not decrypt more than 128 data package one time.When FH_ERR_CIPHER_BUSY return, the data package you send will not be deal, the custmer should decrease the number of data package or run cipher again.Note:When decrypting more than one packaged data, every one package will be calculated using initial vector configured by FH_UNF_CIPHER_ConfigHandle.Previous result will not affect the later result.
+\param[in] hCipher cipher handle
+\param[in] pstDataPkg data package ready for cipher
+\param[in] u32DataPkgNum number of package ready for cipher
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT cipher device have not been initialized
+\retval ::FH_ERR_CIPHER_INVALID_PARA parameter error
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE handle invalid
+\retval ::FH_ERR_CIPHER_BUSY hardware is busy, it can not deal with all data package once time
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_DecryptMulti(FH_HANDLE hCipher, FH_UNF_CIPHER_DATA_S *pstDataPkg, FH_U32 u32DataPkgNum);
+
+/**
+\brief Encrypt multiple packaged data.
+\attention \n
+You can not encrypt more than 128 data package one time. When FH_ERR_CIPHER_BUSY return, the data package you send will not be deal, the custmer should decrease the number of data package or run cipher again.Note:When encrypting more than one packaged data, every one package will be calculated using initial vector configured by FH_UNF_CIPHER_ConfigHandle.Previous result will not affect the later result.
+\param[in] hCipher cipher handle
+\param[in] pstCtrl Cipher control information.
+\param[in] pstDataPkg data package ready for cipher
+\param[in] u32DataPkgNum number of package ready for cipher
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT cipher device have not been initialized
+\retval ::FH_ERR_CIPHER_INVALID_PARA parameter error
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE handle invalid
+\retval ::FH_ERR_CIPHER_BUSY hardware is busy, it can not deal with all data package once time
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_EncryptMultiEx(FH_HANDLE hCipher, FH_UNF_CIPHER_CTRL_S* pstCtrl, FH_UNF_CIPHER_DATA_S *pstDataPkg, FH_U32 u32DataPkgNum);
+
+/**
+\brief Decrypt multiple packaged data.
+\attention \n
+You can not decrypt more than 128 data package one time.When FH_ERR_CIPHER_BUSY return, the data package you send will not be deal, the custmer should decrease the number of data package or run cipher again.Note:When decrypting more than one packaged data, every one package will be calculated using initial vector configured by FH_UNF_CIPHER_ConfigHandle.Previous result will not affect the later result.
+\param[in] hCipher cipher handle
+\param[in] pstCtrl Cipher control information.
+\param[in] pstDataPkg data package ready for cipher
+\param[in] u32DataPkgNum number of package ready for cipher
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT cipher device have not been initialized
+\retval ::FH_ERR_CIPHER_INVALID_PARA parameter error
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE handle invalid
+\retval ::FH_ERR_CIPHER_BUSY hardware is busy, it can not deal with all data package once time
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_DecryptMultiEx(FH_HANDLE hCipher, FH_UNF_CIPHER_CTRL_S* pstCtrl, FH_UNF_CIPHER_DATA_S *pstDataPkg, FH_U32 u32DataPkgNum);
+
+/**
+\brief get tag value.
+\attention \n
+You can get the tag value after encrypt/decrypt with CCM/GCM mode.
+\param[in] hCipher cipher handle
+\param[out] pstTag TAG data
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT cipher device have not been initialized
+\retval ::FH_ERR_CIPHER_INVALID_PARA parameter error
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE handle invalid
+\retval ::FH_ERR_CIPHER_BUSY hardware is busy, it can not deal with all data package once time
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_GetTag(FH_HANDLE hCipher, FH_U8 *pstTag);
+
+/**
+\brief Encrypt the clean key data by KLAD.
+\attention \n
+N/A
+\param[in] enRootKey klad root key.
+\param[in] pu8CleanKey clean key.
+\param[in] enTarget the module who to use this key.
+\param[out] pu8EcnryptKey encrypt key.
+\param[in] u32KeyLen clean key.
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+\retval ::FH_ERR_CIPHER_NOT_INIT The cipher device is not initialized.
+\retval ::FH_ERR_CIPHER_INVALID_POINT The pointer is null.
+\retval ::FH_ERR_CIPHER_INVALID_PARA The parameter is invalid.
+\retval ::FH_ERR_CIPHER_INVALID_HANDLE The handle is invalid.
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_KladEncryptKey(FH_UNF_CIPHER_KEY_SRC_E enRootKey,
+ FH_UNF_CIPHER_KLAD_TARGET_E enTarget,
+ FH_U8 *pu8CleanKey, FH_U8* pu8EcnryptKey, FH_U32 u32KeyLen);
+
+/**
+\brief Init the hash module, if other program is using the hash module, the API will return failure.
+
+\attention \n
+N/A
+
+\param[in] pstHashAttr: The hash calculating structure input.
+\param[out] pHashHandle: The output hash handle.
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_HashInit(FH_UNF_CIPHER_HASH_ATTS_S *pstHashAttr, FH_HANDLE *pHashHandle);
+
+/**
+\brief Calculate the hash, if the size of the data to be calculated is very big and the DDR ram is not enough, this API can calculate the data one block by one block. Attention: The input block length must be 64bytes alingned except for the last block.
+
+\attention \n
+N/A
+
+\param[in] hHashHandl: Hash handle.
+\param[in] pu8InputData: The input data buffer.
+\param[in] u32InputDataLen: The input data length, attention: the block length input must be 64bytes aligned except the last block!
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_HashUpdate(FH_HANDLE hHashHandle, FH_U8 *pu8InputData, FH_U32 u32InputDataLen);
+
+
+
+/**
+\brief Get the final hash value, after calculate all of the data, call this API to get the final hash value and close the handle.If there is some reason need to interupt the calculation, this API should also be call to close the handle.
+
+\attention \n
+N/A
+
+\param[in] hHashHandle: Hash handle.
+\param[out] pu8OutputHash: The final output hash value.
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_HashFinal(FH_HANDLE hHashHandle, FH_U8 *pu8OutputHash);
+
+/**
+\brief compute the hash module
+
+\attention \n
+N/A
+
+\param[in] pstHashAttr: The hash calculating structure input.
+\param[in] u32DataPhyAddr: Physical address of input data.
+\param[in] u32ByteLength: The input data length
+\param[out] pu8OutputHash: The final output hash value.
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_Hash(FH_UNF_CIPHER_HASH_ATTS_S *pstHashAttr, FH_U32 u32DataPhyAddr, FH_U32 u32ByteLength, FH_U8 *pu8OutputHash);
+
+/**
+\brief RSA encryption a plaintext with a RSA public key.
+
+\attention \n
+N/A
+
+\param[in] pstRsaEnc: encryption struct.
+\param[in] pu8Input input data to be encryption
+\param[out] u32InLen: length of input data to be encryption
+\param[out] pu8Output output data to be encryption
+\param[out] pu32OutLen: length of output data to be encryption
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_RsaPublicEnc(FH_UNF_CIPHER_RSA_PUB_ENC_S *pstRsaEnc,
+ FH_U8 *pu8Input, FH_U32 u32InLen,
+ FH_U8 *pu8Output, FH_U32 *pu32OutLen);
+
+/**
+\brief RSA decryption a ciphertext with a RSA private key.
+
+\attention \n
+N/A
+
+\param[in] pstRsaDec: decryption struct.
+\param[in] pu8Input input data to be decryption
+\param[out] u32InLen: length of input data to be decryption
+\param[out] pu8Output output data to be decryption
+\param[out] pu32OutLen: length of output data to be decryption
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_RsaPrivateDec(FH_UNF_CIPHER_RSA_PRI_ENC_S *pstRsaDec,
+ FH_U8 *pu8Input, FH_U32 u32InLen,
+ FH_U8 *pu8Output, FH_U32 *pu32OutLen);
+
+/**
+\brief RSA encryption a plaintext with a RSA private key.
+
+\attention \n
+N/A
+
+\param[in] pstRsaSign: encryption struct.
+\param[in] pu8Input input data to be encryption
+\param[out] u32InLen: length of input data to be encryption
+\param[out] pu8Output output data to be encryption
+\param[out] pu32OutLen: length of output data to be encryption
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_RsaPrivateEnc(FH_UNF_CIPHER_RSA_PRI_ENC_S *pstRsaEnc,
+ FH_U8 *pu8Input, FH_U32 u32InLen,
+ FH_U8 *pu8Output, FH_U32 *pu32OutLen);
+
+/**
+\brief RSA decryption a ciphertext with a RSA public key.
+
+\attention \n
+N/A
+
+\param[in] pstRsaVerify: decryption struct.
+\param[in] pu8Input input data to be decryption
+\param[out] u32InLen: length of input data to be decryption
+\param[out] pu8Output output data to be decryption
+\param[out] pu32OutLen: length of output data to be decryption
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_RsaPublicDec(FH_UNF_CIPHER_RSA_PUB_ENC_S *pstRsaDec,
+ FH_U8 *pu8Input, FH_U32 u32InLen,
+ FH_U8 *pu8Output, FH_U32 *pu32OutLen);
+
+/**
+\brief RSA signature a context with appendix, where a signer's RSA private key is used.
+
+\attention \n
+N/A
+
+\param[in] pstRsaSign: signature struct.
+\param[in] pu8Input input context to be signature, maybe null
+\param[in] u32InLen: length of input context to be signature
+\param[in] pu8HashData hash value of context,if NULL, let pu8HashData = Hash(context) automatically
+\param[out] pu8OutSign output message of signature
+\param[out] pu32OutSignLen: length of message of signature
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_RsaSign(FH_UNF_CIPHER_RSA_SIGN_S *pstRsaSign,
+ FH_U8 *pu8InData, FH_U32 u32InDataLen,
+ FH_U8 *pu8HashData,
+ FH_U8 *pu8OutSign, FH_U32 *pu32OutSignLen);
+
+/**
+\brief RSA signature verification a context with appendix, where a signer's RSA public key is used.
+
+\attention \n
+N/A
+
+\param[in] pstRsaVerify: signature verification struct.
+\param[in] pu8Input input context to be signature verification, maybe null
+\param[in] u32InLen: length of input context to be signature
+\param[in] pu8HashData hash value of context,if NULL, let pu8HashData = Hash(context) automatically
+\param[in] pu8InSign message of signature
+\param[in] pu32InSignLen: length of message of signature
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_RsaVerify(FH_UNF_CIPHER_RSA_VERIFY_S *pstRsaVerify,
+ FH_U8 *pu8InData, FH_U32 u32InDataLen,
+ FH_U8 *pu8HashData,
+ FH_U8 *pu8InSign, FH_U32 u32InSignLen);
+
+
+/**
+\brief Generate a RSA private key.
+
+\attention \n
+N/A
+
+\param[in] u32NumBits: bit numbers of the integer public modulus.
+\param[in] u32Exponent: value of public exponent.
+\param[out] ptRsaPriKey: private key struct.
+
+\retval ::FH_SUCCESS Call this API successful.
+\retval ::FH_FAILURE Call this API fails.
+
+\see \n
+N/A
+*/
+FH_S32 FH_UNF_CIPHER_RsaGenKey(FH_U32 u32NumBits, FH_U32 u32Exponent, FH_UNF_CIPHER_RSA_PRI_KEY_S *pstRsaPriKey);
+
+/** @} */ /** <!-- ==== API declaration end ==== */
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif /* __FH_UNF_CIPHER_H__ */
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index a2bfd784..de8c9431 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -20,7 +20,7 @@
#include <linux/types.h>
#include <net/sock.h>
-#define ALG_MAX_PAGES 16
+#define ALG_MAX_PAGES 128
struct crypto_async_request;
@@ -46,6 +46,7 @@ struct af_alg_control {
struct af_alg_iv *iv;
int op;
unsigned int aead_assoclen;
+ struct af_alg_usr_def usr_def;
};
struct af_alg_type {
diff --git a/include/crypto/sha.h b/include/crypto/sha.h
index c94d3eb1..487e108b 100644
--- a/include/crypto/sha.h
+++ b/include/crypto/sha.h
@@ -22,6 +22,9 @@
#define SHA512_DIGEST_SIZE 64
#define SHA512_BLOCK_SIZE 128
+#define SM3_DIGEST_SIZE 32
+#define SM3_BLOCK_SIZE 64
+
#define SHA1_H0 0x67452301UL
#define SHA1_H1 0xefcdab89UL
#define SHA1_H2 0x98badcfeUL
@@ -88,6 +91,12 @@ struct sha512_state {
u8 buf[SHA512_BLOCK_SIZE];
};
+struct sm3_state {
+ u32 state[SM3_DIGEST_SIZE / 4];
+ u64 count;
+ u8 buf[SM3_BLOCK_SIZE];
+};
+
struct shash_desc;
extern int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h
index cc4d98a7..2d647098 100644
--- a/include/crypto/skcipher.h
+++ b/include/crypto/skcipher.h
@@ -61,7 +61,7 @@ struct crypto_skcipher {
unsigned int ivsize;
unsigned int reqsize;
unsigned int keysize;
-
+ struct af_alg_usr_def usr_def;
struct crypto_tfm base;
};
@@ -276,6 +276,13 @@ static inline unsigned int crypto_skcipher_ivsize(struct crypto_skcipher *tfm)
return tfm->ivsize;
}
+static inline struct af_alg_usr_def*
+crypto_skcipher_usr_def(struct crypto_skcipher *tfm)
+{
+ return &tfm->usr_def;
+}
+
+
static inline unsigned int crypto_skcipher_alg_chunksize(
struct skcipher_alg *alg)
{
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 73fd8b7e..716d5379 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -150,7 +150,7 @@ extern int sysctl_aarp_retransmit_limit;
extern int sysctl_aarp_resolve_time;
#ifdef CONFIG_SYSCTL
-extern void atalk_register_sysctl(void);
+extern int atalk_register_sysctl(void);
extern void atalk_unregister_sysctl(void);
#else
#define atalk_register_sysctl() do { } while(0)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a428aec3..b7212288 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -25,7 +25,7 @@
#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */
#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */
#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */
- /* unused */
+#define CLK_IS_ROOT BIT(4) /* root clk, has no parent */
#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */
#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */
#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 8e82e337..2a3a34aa 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -89,8 +89,7 @@
* of extern inline functions at link time.
* A lot of inline functions can cause havoc with function tracing.
*/
-#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
- !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4)
+#if !defined(CONFIG_OPTIMIZE_INLINING)
#define inline \
inline __attribute__((always_inline, unused)) notrace __gnu_inline
#else
diff --git a/include/linux/console.h b/include/linux/console.h
index d530c462..b6734813 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -202,4 +202,6 @@ extern bool vgacon_text_force(void);
static inline bool vgacon_text_force(void) { return false; }
#endif
+extern void console_init(void);
+
#endif /* _LINUX_CONSOLE_H */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 9de26962..7278aea7 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h>
-
+#include <linux/if_alg.h>
/*
* Autoloaded crypto modules should only use a prefixed name to avoid allowing
* arbitrary modules to be loaded. Loading from userspace may still need the
@@ -182,7 +182,8 @@ struct ablkcipher_request {
struct scatterlist *src;
struct scatterlist *dst;
-
+ /* bind to tfm.. */
+ struct af_alg_usr_def *usr_def;
void *__ctx[] CRYPTO_MINALIGN_ATTR;
};
@@ -724,6 +725,8 @@ static inline u32 crypto_skcipher_mask(u32 mask)
* which operation just finished if it invoked multiple in parallel. This
* state information is unused by the kernel crypto API.
*/
+struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
+ u32 type, u32 mask);
static inline struct crypto_tfm *crypto_ablkcipher_tfm(
struct crypto_ablkcipher *tfm)
@@ -969,6 +972,11 @@ static inline void ablkcipher_request_free(struct ablkcipher_request *req)
kzfree(req);
}
+static inline void ablkcipher_request_set_usrdef(
+ struct ablkcipher_request *req, struct af_alg_usr_def *p_usrdef)
+{
+ req->usr_def = p_usrdef;
+}
/**
* ablkcipher_request_set_callback() - set asynchronous callback function
* @req: request handle
diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h
index f4754282..11534dc3 100644
--- a/include/linux/cryptohash.h
+++ b/include/linux/cryptohash.h
@@ -14,7 +14,8 @@ void sha_transform(__u32 *digest, const char *data, __u32 *W);
#define MD5_MESSAGE_BYTES 64
void md5_transform(__u32 *hash, __u32 const *in);
-
+#ifdef CONFIG_HALFMD4
__u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
+#endif
#endif
diff --git a/include/linux/export.h b/include/linux/export.h
index 2a0f61fb..c3babe93 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -76,7 +76,7 @@ extern struct module __this_module;
*/
#define __EXPORT_SYMBOL(sym, sec) === __KSYM_##sym ===
-#elif defined(CONFIG_TRIM_UNUSED_KSYMS)
+#elif defined(CONFIG_TRIM_UNUSED_KSYMS) && !defined(MODULE)
#include <generated/autoksyms.h>
diff --git a/include/linux/fh_acw.h b/include/linux/fh_acw.h
new file mode 100644
index 00000000..959f58db
--- /dev/null
+++ b/include/linux/fh_acw.h
@@ -0,0 +1,126 @@
+#ifndef __FH_ACW_H
+#define __FH_ACW_H
+
+#define _FHIOWR(x, y, z) y
+#define FH_AUDIO_IOCTL_BASE 'M'
+#define AC_INIT_CAPTURE_MEM _FHIOWR(FH_AUDIO_IOCTL_BASE, 0, int)
+#define AC_INIT_PLAYBACK_MEM _FHIOWR(FH_AUDIO_IOCTL_BASE, 1, int)
+#define AC_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 2, int)
+#define AC_SET_INPUT_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 3, int)
+#define AC_SET_OUTPUT_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 4, int)
+#define AC_AI_EN _FHIOWR(FH_AUDIO_IOCTL_BASE, 5, int)
+#define AC_AO_EN _FHIOWR(FH_AUDIO_IOCTL_BASE, 6, int)
+#define AC_AI_DISABLE _FHIOWR(FH_AUDIO_IOCTL_BASE, 7, int)
+#define AC_AO_DISABLE _FHIOWR(FH_AUDIO_IOCTL_BASE, 8, int)
+#define AC_AI_PAUSE _FHIOWR(FH_AUDIO_IOCTL_BASE, 9, int)
+#define AC_AI_RESUME _FHIOWR(FH_AUDIO_IOCTL_BASE, 10, int)
+#define AC_AO_PAUSE _FHIOWR(FH_AUDIO_IOCTL_BASE, 11, int)
+#define AC_AO_RESUME _FHIOWR(FH_AUDIO_IOCTL_BASE, 12, int)
+#define AC_AI_READ _FHIOWR(FH_AUDIO_IOCTL_BASE, 13, int)
+#define AC_AO_WRITE _FHIOWR(FH_AUDIO_IOCTL_BASE, 14, int)
+#define AC_AI_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 15, int)
+#define AC_AO_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 16, int)
+#define AC_AI_MICIN_SET_VOL _FHIOWR(FH_AUDIO_IOCTL_BASE, 17, int)
+#define AC_AEC_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 18, int)
+#define AC_NR_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 19, int)
+#define AC_NR2_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 20, int)
+#define AC_AGC_SET_CONFIG _FHIOWR(FH_AUDIO_IOCTL_BASE, 21, int)
+#define AC_WORK_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 22, int)
+#define AC_AI_READ_FRAME_EXT _FHIOWR(FH_AUDIO_IOCTL_BASE, 23, int)
+#define AC_AO_SET_MODE _FHIOWR(FH_AUDIO_IOCTL_BASE, 24, int)
+#define AC_USING_EXTERNAL_CODEC _FHIOWR(FH_AUDIO_IOCTL_BASE, 25, int)
+#define AC_EXT_INTF _FHIOWR(FH_AUDIO_IOCTL_BASE, 100, int)
+
+enum io_select{
+ mic_in = 0,
+ line_in = 1,
+ speaker_out = 2,
+ line_out = 3,
+};
+
+struct fh_audio_cfg_arg{
+ int io_type;
+ int volume;
+ int rate;
+ int frame_bit;
+ int channels;
+ int buffer_size;
+ int period_size;
+};
+
+struct fh_audio_ai_read_frame_ext {
+ unsigned int len;
+ unsigned char *data;
+ unsigned long long pts;
+};
+
+enum audio_type {
+ capture = 0, playback,
+};
+
+enum audio_state {
+ STATE_NORMAL = 0, STATE_INIT, STATE_STOP, STATE_RUN, STATE_PAUSE
+};
+
+struct infor_record_t {
+ int record_pid;
+ int play_pid;
+};
+
+struct audio_config {
+ int rate;
+ int volume;
+ enum io_select io_type;
+ int frame_bit;
+ int channels;
+ int buffer_size;
+ int period_size;
+ int buffer_bytes;
+ int period_bytes;
+ int start_threshold;
+ int stop_threshold;
+};
+
+struct audio_ptr_t {
+ struct audio_config cfg;
+ enum audio_state state;
+ long size;
+ int hw_ptr;
+ int appl_ptr;
+ spinlock_t lock;
+ struct device dev;
+ u8 *area; /*virtual pointer*/
+ dma_addr_t addr; /*physical address*/
+ u8 *mmap_addr;
+};
+
+struct fh_audio_cfg {
+ struct audio_ptr_t capture;
+ struct audio_ptr_t playback;
+ wait_queue_head_t readqueue;
+ wait_queue_head_t writequeue;
+ struct semaphore sem_capture;
+ struct semaphore sem_playback;
+};
+
+struct fh_audio_dma {
+ struct dma_chan *chan;
+ struct fh_cyclic_desc *cdesc;
+};
+
+struct channel_assign {
+ int capture_channel;
+ int playback_channel;
+};
+
+struct audio_dev {
+ struct channel_assign channel_assign;
+ int dma_master;
+ int dma_rx_hs_num;
+ int dma_tx_hs_num;
+ struct fh_audio_cfg audio_config;
+ struct miscdevice fh_audio_miscdev;
+};
+
+#endif
+
diff --git a/include/linux/fh_clk_miscdev.h b/include/linux/fh_clk_miscdev.h
new file mode 100644
index 00000000..5671bc21
--- /dev/null
+++ b/include/linux/fh_clk_miscdev.h
@@ -0,0 +1,20 @@
+
+#ifndef FH_CLK_MISCDEV_H_
+#define FH_CLK_MISCDEV_H_
+
+#include <mach/clock.h>
+
+#define DEVICE_NAME "fh_clk_miscdev"
+
+#define CLK_IOCTL_MAGIC 'c'
+#define ENABLE_CLK _IOWR(CLK_IOCTL_MAGIC, 0, unsigned int)
+#define DISABLE_CLK _IOWR(CLK_IOCTL_MAGIC, 1, unsigned int)
+#define SET_CLK_RATE _IOWR(CLK_IOCTL_MAGIC, 2, unsigned int)
+#define GET_CLK_RATE _IOWR(CLK_IOCTL_MAGIC, 3, unsigned int)
+#define SET_PMU _IOWR(CLK_IOCTL_MAGIC, 4, unsigned int)
+#define GET_PMU _IOWR(CLK_IOCTL_MAGIC, 5, unsigned int)
+
+#define CLK_IOCTL_MAXNR 8
+
+
+#endif /* FH_CLK_MISCDEV_H_ */
diff --git a/include/linux/fh_dmac.h b/include/linux/fh_dmac.h
new file mode 100644
index 00000000..1d2b1440
--- /dev/null
+++ b/include/linux/fh_dmac.h
@@ -0,0 +1,279 @@
+#ifndef FH_DMAC_H
+#define FH_DMAC_H
+
+#include <linux/dmaengine.h>
+#include <mach/fh_dma_plat.h>
+
+#ifdef CONFIG_FH_DMAC
+/* Platform-configurable bits in CFG_HI */
+#define FHC_CFGH_FCMODE (1 << 0)
+#define FHC_CFGH_FIFO_MODE (1 << 1)
+#define FHC_CFGH_PROTCTL(x) ((x) << 2)
+#define FHC_CFGH_SRC_PER(x) ((x) << 7)
+#define FHC_CFGH_DST_PER(x) ((x) << 11)
+#endif
+
+enum fh_dma_slave_increment {
+ FH_DMA_SLAVE_INC,
+ FH_DMA_SLAVE_DEC,
+ FH_DMA_SLAVE_FIX,
+};
+
+enum fh_dmac_flags {
+ FH_DMA_IS_CYCLIC = 0,
+ FH_DMA_IS_SOFT_LLP = 1,
+};
+
+/**
+ * enum fh_dma_slave_width - DMA slave register access width.
+ * @DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
+ * @DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
+ * @DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
+ */
+enum fh_dma_slave_width {
+ FH_DMA_SLAVE_WIDTH_8BIT,
+ FH_DMA_SLAVE_WIDTH_16BIT,
+ FH_DMA_SLAVE_WIDTH_32BIT,
+};
+
+/* bursts size */
+enum fh_dma_msize {
+ FH_DMA_MSIZE_1,
+ FH_DMA_MSIZE_4,
+ FH_DMA_MSIZE_8,
+ FH_DMA_MSIZE_16,
+ FH_DMA_MSIZE_32,
+ FH_DMA_MSIZE_64,
+ FH_DMA_MSIZE_128,
+ FH_DMA_MSIZE_256,
+};
+
+/* flow controller */
+enum fh_dma_fc {
+ FH_DMA_FC_D_M2M,
+ FH_DMA_FC_D_M2P,
+ FH_DMA_FC_D_P2M,
+ FH_DMA_FC_D_P2P,
+ FH_DMA_FC_P_P2M,
+ FH_DMA_FC_SP_P2P,
+ FH_DMA_FC_P_M2P,
+ FH_DMA_FC_DP_P2P,
+};
+
+/**
+ * struct fh_dma_slave - Controller-specific information about a slave
+ *
+ * @dma_dev: required DMA master device
+ * @tx_reg: physical address of data register used for
+ * memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ * peripheral-to-memory transfers
+ * @reg_width: peripheral register width
+ * @cfg_hi: Platform-specific initializer for the CFG_HI register
+ * @cfg_lo: Platform-specific initializer for the CFG_LO register
+ * @src_master: src master for transfers on allocated channel.
+ * @dst_master: dest master for transfers on allocated channel.
+ * @src_msize: src burst size.
+ * @dst_msize: dest burst size.
+ * @fc: flow controller for DMA transfer
+ */
+struct fh_dma_slave {
+ struct device *dma_dev;
+ dma_addr_t tx_reg;
+ dma_addr_t rx_reg;
+ enum fh_dma_slave_width reg_width;
+ u32 cfg_hi;
+ u32 cfg_lo;
+ u8 src_master;
+ u8 dst_master;
+ u8 src_msize;
+ u8 dst_msize;
+ u8 fc;
+};
+
+/* DMA API extensions */
+struct fh_cyclic_desc {
+ struct fh_desc **desc;
+ unsigned long periods;
+ void (*period_callback)(void *param);
+ void *period_callback_param;
+};
+
+struct fh_dma_extra {
+ u32 sinc;
+ u32 dinc;
+ u32 protctl_flag;
+ u32 protctl_data;
+ u32 master_flag;
+ u32 src_master;
+ u32 dst_master;
+};
+
+struct fh_dma_chan {
+ struct dma_chan chan;
+ void __iomem *ch_regs;
+ u8 mask;
+ u8 priority;
+ enum dma_transfer_direction direction;
+ bool paused;
+ bool initialized;
+
+ /* software emulation of the LLP transfers */
+ struct list_head *tx_node_active;
+
+ spinlock_t lock;
+
+ /* these other elements are all protected by lock */
+ unsigned long flags;
+ struct list_head active_list;
+ struct list_head queue;
+ struct list_head free_list;
+ u32 residue;
+ struct fh_cyclic_desc *cdesc;
+
+ unsigned int descs_allocated;
+
+ /* hardware configuration */
+ unsigned int block_size;
+ bool nollp;
+
+ /* custom slave configuration */
+ unsigned int request_line;
+ unsigned char src_master;
+ unsigned char dst_master;
+ struct fh_dma_extra ext_para;
+ /* configuration passed via DMA_SLAVE_CONFIG */
+ struct dma_slave_config dma_sconfig;
+#ifdef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+ void *dma_vaddr;
+ dma_addr_t dma_paddr;
+#endif
+};
+
+struct fh_dma {
+ struct dma_device dma;
+ void __iomem *regs;
+#ifndef CONFIG_CHANNEL_ALLOC_MEM_CLASSICS
+ struct dma_pool *desc_pool;
+#endif
+ struct tasklet_struct tasklet;
+ struct clk *clk;
+
+ u8 all_chan_mask;
+
+ /* hardware configuration */
+ unsigned char nr_masters;
+ unsigned char data_width[4];
+
+ struct fh_dma_chan chan[0];
+};
+
+/* LLI == Linked List Item; a.k.a. DMA block descriptor */
+struct fh_lli {
+ /* values that are not changed by hardware */
+ u32 sar;
+ u32 dar;
+ u32 llp; /* chain to next lli */
+ u32 ctllo;
+ /* values that may get written back: */
+ u32 ctlhi;
+ /* sstat and dstat can snapshot peripheral register state.
+ * silicon config may discard either or both...
+ */
+ u32 sstat;
+ u32 dstat;
+};
+
+struct fh_desc {
+ /* FIRST values the hardware uses */
+ struct fh_lli lli;
+
+ /* THEN values for driver housekeeping */
+ struct list_head desc_node;
+ struct list_head tx_list;
+ struct dma_async_tx_descriptor txd;
+ size_t len;
+ size_t total_len;
+};
+
+
+#define to_fh_desc(h) list_entry(h, struct fh_desc, desc_node)
+
+
+static inline int axi_dma_lock(axi_dma_lock_t *p, FH_UINT32 time_out)
+{
+ _axi_dma_lock(p, time_out);
+ return 0;
+}
+
+static inline void* axi_dma_malloc_desc(void* pri, FH_UINT32 size, FH_UINT32* phy_back){
+ // struct fh_axi_dma_adapt *fh_axi_adapt_obj;
+ // fh_axi_adapt_obj = (struct fh_axi_dma_adapt *)pri;
+ return dma_alloc_coherent(pri, size, (dma_addr_t *)phy_back, GFP_KERNEL);
+}
+
+static inline void axi_dma_free_desc(void* pri, FH_UINT32 size, void *vir, FH_UINT32 phy_add){
+ // struct fh_axi_dma_adapt *fh_axi_adapt_obj;
+ // fh_axi_adapt_obj = (struct fh_axi_dma_adapt *)pri;
+ dma_free_coherent(pri, size, vir, phy_add);
+}
+#define axi_dma_free_desc(core_pri, size, vir, phy) dma_free_coherent(core_pri, size, vir, phy)
+
+static inline void axi_dma_clean_invalidated_desc(FH_UINT32 buffer, FH_UINT32 size)
+{
+
+}
+
+static inline void axi_dma_clean_desc(FH_UINT32 buffer, FH_UINT32 size)
+{
+
+}
+
+static inline void axi_dma_invalidate_desc(FH_UINT32 buffer, FH_UINT32 size)
+{
+
+}
+
+/* data cache flush.. if data buff just in no cache mem; no need to care*/
+static inline void axi_dma_clean_invalidated_dcache(FH_UINT32 buffer, FH_UINT32 size)
+{
+
+}
+
+static inline void axi_dma_clean_dcache(FH_UINT32 buffer, FH_UINT32 size)
+{
+
+}
+
+static inline void axi_dma_invalidate_dcache(FH_UINT32 buffer, FH_UINT32 size)
+{
+
+}
+
+static inline struct fh_dma_chan *to_fh_dma_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct fh_dma_chan, chan);
+}
+
+static inline struct fh_dma *to_fh_dma(struct dma_device *ddev)
+{
+ return container_of(ddev, struct fh_dma, dma);
+}
+
+static inline struct fh_desc *
+txd_to_fh_desc(struct dma_async_tx_descriptor *txd)
+{
+ return container_of(txd, struct fh_desc, txd);
+}
+
+struct fh_cyclic_desc *fh_dma_cyclic_prep(struct dma_chan *chan,
+ dma_addr_t buf_addr, size_t buf_len, size_t period_len,
+ enum dma_transfer_direction direction);
+void fh_dma_cyclic_free(struct dma_chan *chan);
+int fh_dma_cyclic_start(struct dma_chan *chan);
+void fh_dma_cyclic_stop(struct dma_chan *chan);
+
+dma_addr_t fh_dma_get_src_addr(struct dma_chan *chan);
+dma_addr_t fh_dma_get_dst_addr(struct dma_chan *chan);
+
+#endif /* FH_DMAC_H */
diff --git a/include/linux/fh_efuse.h b/include/linux/fh_efuse.h
new file mode 100644
index 00000000..2ab0e08d
--- /dev/null
+++ b/include/linux/fh_efuse.h
@@ -0,0 +1,111 @@
+/*
+ * fh_efuse.h
+ *
+ * Created on: Aug 9, 2016
+ * Author: duobao
+ */
+
+#ifndef FH_EFUSE_H_
+#define FH_EFUSE_H_
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/bug.h>
+#include <linux/completion.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <crypto/if_alg.h>
+/****************************************************************************
+ * #define section
+ * add constant #define here if any
+ ***************************************************************************/
+/*#define FH_EFUSE_PROC_FILE "driver/efuse"*/
+#define MAX_EFUSE_MAP_SIZE 8
+
+#define IOCTL_EFUSE_CHECK_PRO 0
+#define IOCTL_EFUSE_WRITE_KEY 1
+#define IOCTL_EFUSE_CHECK_LOCK 2
+#define IOCTL_EFUSE_TRANS_KEY 3
+#define IOCTL_EFUSE_SWITCH_CPU_KEY_MODE 4
+#define IOCTL_EFUSE_SWITCH_EFUSE_KEY_MODE 5
+#define IOCTL_EFUSE_CHECK_ERROR 6
+#define IOCTL_EFUSE_READ_KEY 7
+#define IOCTL_EFUSE_SET_LOCK 8
+#define IOCTL_EFUSE_SET_MAP_PARA_4_TO_1 9
+#define IOCTL_EFUSE_SET_MAP_PARA_1_TO_1 10
+#define IOCTL_EFUSE_CLR_MAP_PARA 11
+
+#define IOCTL_EFUSE_WRITE_ENTRY 20
+#define IOCTL_EFUSE_READ_ENTRY 21
+#define EFUSE_NEED_TRANS 0x55
+/****************************************************************************
+ * ADT section
+ * add Abstract Data Type definition here
+ ***************************************************************************/
+
+struct efuse_status {
+ /*bit 1 means could write..0 not write*/
+ u32 protect_bits[2];
+ /*bit 1 means cpu couldn't read efuse entry data...*/
+ u32 efuse_apb_lock;
+ u32 aes_ahb_lock;
+ u32 error;
+};
+
+typedef struct {
+ u32 efuse_entry_no; /*from 0 ~ 31*/
+ u8 *key_buff;
+ u32 key_size;
+ u32 trans_key_start_no; /*from 0 ~ 7*/
+ u32 trans_key_size; /*max 8*/
+ struct efuse_status status;
+} EFUSE_INFO;
+
+struct wrap_efuse_obj {
+ void *regs;
+ struct clk *clk;
+ /*write key*/
+ u32 efuse_entry_no; /*from 0 ~ 31*/
+ u8 *key_buff;
+ u32 key_size;
+ /*trans key*/
+ u32 trans_key_start_no; /*from 0 ~ 7*/
+ u32 trans_key_size; /*max 8*/
+ /*status*/
+ struct efuse_status status;
+ u32 open_flag;
+ /*add check if need efuse transkey*/
+ u32 efuse_trans_flag;
+ /* for old driver just check size.
+ for have mapping func, should check the adv_info para.*/
+ u32 old_size;
+ struct af_alg_usr_def old_usr_def;
+};
+
+
+/****************************************************************************
+ * extern variable declaration section
+ ***************************************************************************/
+
+/****************************************************************************
+ * section
+ * add function prototype here if any
+ ***************************************************************************/
+void efuse_trans_key(struct wrap_efuse_obj *obj, u32 start_no,
+u32 size, struct af_alg_usr_def *p_alg);
+unsigned char efuse_read_debug_entry(u32 entry);
+void refresh_efuse(struct wrap_efuse_obj *obj);
+void efuse_read_entry(struct wrap_efuse_obj *obj,
+u32 key, u32 start_entry, u8 *buff, u32 size);
+int fh_efuse_secure_check(struct wrap_efuse_obj *obj,
+u32 start_no, u32 size, struct af_alg_usr_def *p_alg);
+#endif /* FH_EFUSE_H_ */
diff --git a/include/linux/fh_pwm.h b/include/linux/fh_pwm.h
new file mode 100644
index 00000000..e66781e8
--- /dev/null
+++ b/include/linux/fh_pwm.h
@@ -0,0 +1,59 @@
+#ifndef _PWM_FULLHAN_H_
+#define _PWM_FULLHAN_H_
+
+#include <linux/ioctl.h>
+
+#define DEVICE_NAME "fh_pwm"
+#define FH_PWM_PROC_FILE "driver/pwm"
+
+#define PWM_IOCTL_MAGIC 'p'
+#define ENABLE_PWM _IOWR(PWM_IOCTL_MAGIC, 0, __u32)
+#define DISABLE_PWM _IOWR(PWM_IOCTL_MAGIC, 1, __u32)
+
+#define SET_PWM_DUTY_CYCLE _IOWR(PWM_IOCTL_MAGIC, 2, __u32)
+#define GET_PWM_DUTY_CYCLE _IOWR(PWM_IOCTL_MAGIC, 3, __u32)
+#define SET_PWM_DUTY_CYCLE_PERCENT _IOWR(PWM_IOCTL_MAGIC, 4, __u32)
+#define SET_PWM_ENABLE _IOWR(PWM_IOCTL_MAGIC, 5, __u32)
+#define ENABLE_MUL_PWM _IOWR(PWM_IOCTL_MAGIC, 6, __u32)
+#define ENABLE_FINSHALL_INTR _IOWR(PWM_IOCTL_MAGIC, 7, __u32)
+#define ENABLE_FINSHONCE_INTR _IOWR(PWM_IOCTL_MAGIC, 8, __u32)
+#define DISABLE_FINSHALL_INTR _IOWR(PWM_IOCTL_MAGIC, 9, __u32)
+#define DISABLE_FINSHONCE_INTR _IOWR(PWM_IOCTL_MAGIC, 10, __u32)
+#define WAIT_PWM_FINSHALL _IOWR(PWM_IOCTL_MAGIC, 12, __u32)
+
+#define PWM_IOCTL_MAXNR 16
+
+struct fh_pwm_config
+{
+ unsigned int period_ns;
+ unsigned int duty_ns;
+ unsigned int pulses;
+#define FH_PWM_STOPLVL_LOW (0x0)
+#define FH_PWM_STOPLVL_HIGH (0x3)
+#define FH_PWM_STOPLVL_KEEP (0x1)
+
+#define FH_PWM_STOPCTRL_ATONCE (0x10)
+#define FH_PWM_STOPCTRL_AFTERFINISH (0x00)
+ unsigned int stop;
+ unsigned int delay_ns;
+ unsigned int phase_ns;
+ unsigned int percent;
+ unsigned int finish_once;
+ unsigned int finish_all;
+};
+
+struct fh_pwm_status {
+ unsigned int done_cnt;
+ unsigned int total_cnt;
+ unsigned int busy;
+ unsigned int error;
+};
+
+struct fh_pwm_chip_data
+{
+ int id;
+ struct fh_pwm_config config;
+ struct fh_pwm_status status;
+};
+
+#endif /* _PWM_FULLHAN_H_ */
diff --git a/include/linux/fh_rtc_v2.h b/include/linux/fh_rtc_v2.h
new file mode 100644
index 00000000..c1e2aba2
--- /dev/null
+++ b/include/linux/fh_rtc_v2.h
@@ -0,0 +1,174 @@
+#ifndef FH_RTC_V2_H_
+#define FH_RTC_V2_H_
+
+#define FH_RTC_IOCTL_MEM_BASE 'A'
+#define GET_TSENSOR_DATA _IOWR(FH_RTC_IOCTL_MEM_BASE, 0, int)
+#define GET_CURRENT_OFFSET_DATA _IOWR(FH_RTC_IOCTL_MEM_BASE, 1, int)
+#define GET_CURRENT_OFFSET_IDX _IOWR(FH_RTC_IOCTL_MEM_BASE, 2, int)
+#define RTC_GET_LUT _IOWR(FH_RTC_IOCTL_MEM_BASE, 3, int)
+#define RTC_SET_LUT _IOWR(FH_RTC_IOCTL_MEM_BASE, 4, int)
+#define GET_REG_VALUE _IOWR(FH_RTC_IOCTL_MEM_BASE, 5, int)
+#define SET_REG_VALUE _IOWR(FH_RTC_IOCTL_MEM_BASE, 6, int)
+#define GET_TEMP_VALUE _IOWR(FH_RTC_IOCTL_MEM_BASE, 7, int)
+
+#define SEC_BIT_START 0
+#define SEC_VAL_MASK 0x3f
+
+#define MIN_BIT_START 6
+#define MIN_VAL_MASK 0xfc0
+
+#define HOUR_BIT_START 12
+#define HOUR_VAL_MASK 0x1f000
+
+#define DAY_BIT_START 17
+#define DAY_VAL_MASK 0xfffe0000
+
+#define FH_RTC_ISR_SEC_POS (1<<0)
+#define FH_RTC_ISR_MIN_POS (1<<1)
+#define FH_RTC_ISR_HOUR_POS (1<<2)
+#define FH_RTC_ISR_DAY_POS (1<<3)
+#define FH_RTC_ISR_ALARM_POS (1<<4)
+#define FH_RTC_ISR_POWERFAIL_POS (1<<5)
+#define FH_RTC_ISR_RX_CRC_ERR_INT (1<<6)
+#define FH_RTC_ISR_RX_COM_ERR_INT (1<<7)
+#define FH_RTC_LEN_ERR_INT (1<<8)
+
+/* input: val=fh_rtc_get_time(base_addr)*/
+#define FH_GET_RTC_SEC(val) ((val & SEC_VAL_MASK) >> SEC_BIT_START)
+#define FH_GET_RTC_MIN(val) ((val & MIN_VAL_MASK) >> MIN_BIT_START)
+#define FH_GET_RTC_HOUR(val) ((val & HOUR_VAL_MASK) >> HOUR_BIT_START)
+#define FH_GET_RTC_DAY(val) ((val & DAY_VAL_MASK) >> DAY_BIT_START)
+
+#define ELAPSED_LEAP_YEARS(y) (((y-1)/4)-((y-1)/100)+((y+299)/400)-17)
+#define OUT_TEMP(y) (y/4096*235-73)
+
+#define FH_RTC_MISC_DEVICE_NAME "fh_rtc_misc"
+
+enum {
+ init_done = 1,
+ initing = 0
+
+};
+
+/****************************************************
+* Function Name : fh_rtc_interrupt_disabel
+* Description : disabale rtc interrupt
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ ****************************************************/
+#define fh_rtc_interrupt_disabel(base_addr) \
+SET_REG(base_addr+REG_RTC_INT_EN, DISABLE)
+
+/******************************************************
+* Function Name : fh_rtc_get_int_status
+* Description : get rtc current interrupt status
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ ******************************************************/
+#define fh_rtc_get_int_status(base_addr) \
+GET_REG(base_addr+FH_RTC_INT_STAT)
+/******************************************************
+* Function Name : fh_rtc_enable_interrupt
+* Description : enable rtc interrupt
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ ******************************************************/
+#define fh_rtc_enable_interrupt(base_addr, value) \
+SET_REG(base_addr+FH_RTC_INT_EN, \
+value|GET_REG(base_addr+FH_RTC_INT_EN))
+
+
+/*******************************************************
+* Function Name : fh_rtc_get_enabled_interrupt
+* Description : get rtc current interrupt enabled
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ ******************************************************/
+#define fh_rtc_get_enabled_interrupt(base_addr) \
+GET_REG(base_addr+FH_RTC_INT_EN)
+/********************************************************
+* Function Name : fh_rtc_set_mask_interrupt
+* Description : set rtc interrupt mask
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ *******************************************************/
+#define fh_rtc_set_mask_interrupt(base_addr, value) \
+SET_REG(base_addr+FH_RTC_INT_EN, value|GET_REG(base_addr+FH_RTC_INT_EN))
+/********************************************************
+* Function Name : fh_rtc_get_offset
+* Description : get rtc offset
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ *******************************************************/
+#define fh_rtc_get_offset(base_addr) \
+GET_REG(base_addr+FH_RTC_OFFSET)
+/********************************************************
+* Function Name : fh_rtc_get_power_fail
+* Description : get rtc power fail register
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ ******************************************************/
+#define fh_rtc_get_power_fail(base_addr) \
+GET_REG(base_addr+FH_RTC_POWER_FAIL)
+
+/********************************************************
+* Function Name : fh_rtc_get_sync
+* Description : get rtc sync register value
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ *********************************************************/
+#define fh_rtc_get_sync(base_addr) \
+GET_REG(base_addr+FH_RTC_SYNC)
+
+/**********************************************************
+* Function Name : fh_rtc_set_sync
+* Description : set rtc sync register value
+* Input : rtc base addr,init_done/initing
+* Output : None
+* Return : None
+*
+************************************************************/
+#define fh_rtc_set_sync(base_addr, value) \
+SET_REG(base_addr+FH_RTC_SYNC, value)
+
+/***********************************************************
+* Function Name : fh_rtc_get_debug
+* Description : get rtc debug register value
+* Input : rtc base addr
+* Output : None
+* Return : None
+*
+ **********************************************************/
+#define fh_rtc_get_debug(base_addr) \
+GET_REG(base_addr+FH_RTC_DEBUG)
+
+/************************************************************
+* Function Name : fh_rtc_set_debug
+* Description : set rtc debug register value
+* Input : rtc base addr,x pclk
+* Output : None
+* Return : None
+*
+ ***********************************************************/
+#define fh_rtc_set_debug(base_addr, value) \
+SET_REG(base_addr+FH_RTC_DEBUG, value)
+
+int fh_rtc_get_tsensor_data(int *data, int *temp);
+
+#endif /* FH_RTC_V2_H_ */
diff --git a/include/linux/fh_simple_timer.h b/include/linux/fh_simple_timer.h
new file mode 100644
index 00000000..659ec203
--- /dev/null
+++ b/include/linux/fh_simple_timer.h
@@ -0,0 +1,39 @@
+#ifndef FH_SIMPLE_TIMER_H_
+#define FH_SIMPLE_TIMER_H_
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/time.h>
+#include <linux/ktime.h>
+#include <linux/timerqueue.h>
+#include <mach/fh_predefined.h>
+
+#define SIMPLE_TIMER_BASE 2
+
+enum simple_timer_state {
+ SIMPLE_TIMER_STOP,
+ SIMPLE_TIMER_START,
+ SIMPLE_TIMER_ERROR,
+};
+
+struct fh_simple_timer
+{
+ struct timerqueue_node node;
+ ktime_t it_interval; /* timer period */
+ ktime_t it_value; /* timer expiration */
+ ktime_t it_delay;
+ void (*function) (void *);
+ void *param;
+};
+
+
+int fh_simple_timer_interrupt(void);
+int fh_simple_timer_create(struct fh_simple_timer *tim);
+int fh_timer_start(void);
+int fh_simple_timer_init(unsigned int base,unsigned int clkbase);
+int fh_simple_timer_periodic_start(struct fh_simple_timer *tim);
+int fh_simple_timer_periodic_stop(void);
+
+#endif /* FH_SIMPLE_TIMER_H_ */
diff --git a/include/linux/init.h b/include/linux/init.h
index 0cca4142..03ab1d61 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -215,6 +215,14 @@ extern bool initcall_debug;
static initcall_t __initcall_##fn \
__used __section(.security_initcall.init) = fn
+#ifdef CONFIG_DEFERRED_INIICALLS
+#define deferred_initcall(fn) \
+ static initcall_t __initcall_##fn \
+ __used __section(.deferred_initcall.init) = fn
+
+#define deferred_module_init(x) deferred_initcall(x)
+#endif
+
struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 722698a4..d3b21753 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -22,6 +22,7 @@
/*#define ADB_MOUSE_MINOR 10 FIXME OBSOLETE */
#define WATCHDOG_MINOR 130 /* Watchdog timer */
#define TEMP_MINOR 131 /* Temperature Sensor */
+#define CIPHER_MINOR 132 /* Fullhan Cipher */
#define RTC_MINOR 135
#define EFI_RTC_MINOR 136 /* EFI Time services */
#define VHCI_MINOR 137
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 493d0793..610d9b34 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2021,6 +2021,9 @@ extern unsigned long mmap_region(struct file *file, unsigned long addr,
extern unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot, unsigned long flags,
vm_flags_t vm_flags, unsigned long pgoff, unsigned long *populate);
+extern unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flag, unsigned long pgoff);
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
static inline unsigned long
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 2b953eb8..5cbc7764 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -116,6 +116,8 @@ struct mmc_data {
#define MMC_DATA_WRITE (1 << 8)
#define MMC_DATA_READ (1 << 9)
+#define MMC_DATA_STREAM (1 << 10)
+
unsigned int bytes_xfered;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 0b243944..4c9ea22e 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -396,6 +396,8 @@ struct mmc_host {
int dsr_req; /* DSR value is valid */
u32 dsr; /* optional driver stage (DSR) value */
+ unsigned int rescan_count;
+ unsigned int rescan_max_num;
unsigned long private[0] ____cacheline_aligned;
};
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 13f8052b..e3793f10 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -127,6 +127,35 @@ struct mtd_ooblayout_ops {
struct mtd_oob_region *oobfree);
};
+/*
+ * Internal ECC layout control structure. For historical reasons, there is a
+ * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
+ * for export to user-space via the ECCGETLAYOUT ioctl.
+ * nand_ecclayout should be expandable in the future simply by the above macros.
+ */
+struct nand_ecclayout {
+ __u32 eccbytes;
+ __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
+ __u32 oobavail;
+ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
+};
+
+
+/*
+ * oob operation modes
+ *
+ * MTD_OOB_PLACE: oob data are placed at the given offset
+ * MTD_OOB_AUTO: oob data are automatically placed at the free areas
+ * which are defined by the ecclayout
+ * MTD_OOB_RAW: mode to read oob and data without doing ECC checking
+ */
+typedef enum {
+ MTD_OOB_PLACE,
+ MTD_OOB_AUTO,
+ MTD_OOB_RAW,
+} mtd_oob_mode_t;
+
+
/**
* struct mtd_pairing_info - page pairing information
*
@@ -546,8 +575,8 @@ struct mtd_notifier {
};
-extern void register_mtd_user (struct mtd_notifier *new);
-extern int unregister_mtd_user (struct mtd_notifier *old);
+extern void register_mtd_user(struct mtd_notifier *new);
+extern int unregister_mtd_user(struct mtd_notifier *old);
void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
void mtd_erase_callback(struct erase_info *instr);
@@ -566,4 +595,26 @@ static inline int mtd_is_bitflip_or_eccerr(int err) {
unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
+/*
+ * Debugging macro and defines
+ */
+#define MTD_DEBUG_LEVEL0 (0) /* Quiet */
+#define MTD_DEBUG_LEVEL1 (1) /* Audible */
+#define MTD_DEBUG_LEVEL2 (2) /* Loud */
+#define MTD_DEBUG_LEVEL3 (3) /* Noisy */
+
+#ifdef CONFIG_MTD_DEBUG
+#define DEBUG(n, args...) \
+ do { \
+ if (n <= CONFIG_MTD_DEBUG_VERBOSE) \
+ printk(KERN_INFO args); \
+ } while (0)
+#else /* CONFIG_MTD_DEBUG */
+#define DEBUG(n, args...) \
+ do { \
+ } while (0)
+
+#endif /* CONFIG_MTD_DEBUG */
+
+
#endif /* __MTD_MTD_H__ */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index d8905a22..b13a1415 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -928,6 +928,10 @@ static inline void nand_set_controller_data(struct nand_chip *chip, void *priv)
#define NAND_MFR_SANDISK 0x45
#define NAND_MFR_INTEL 0x89
#define NAND_MFR_ATO 0x9b
+#define NAND_MFR_WINBOND 0xEF
+#define NAND_MFR_GD 0xD1
+
+
/* The maximum expected count of bytes in the NAND ID sequence */
#define NAND_MAX_ID_LEN 8
diff --git a/include/linux/mtd/spi-nand.h b/include/linux/mtd/spi-nand.h
new file mode 100644
index 00000000..93b7b862
--- /dev/null
+++ b/include/linux/mtd/spi-nand.h
@@ -0,0 +1,353 @@
+/*-
+ *
+ * Copyright (c) 2009-2014 Micron Technology, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Peter Pan <peterpandong at micron.com>
+ *
+ * based on mt29f_spinand.h
+ */
+#ifndef __LINUX_MTD_SPI_NAND_H
+#define __LINUX_MTD_SPI_NAND_H
+
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/flashchip.h>
+
+
+/*
+ * Standard SPI-NAND flash commands
+ */
+#define SPINAND_CMD_READ 0x13
+#define SPINAND_CMD_READ_RDM 0x03
+#define SPINAND_CMD_PROG_LOAD 0x02
+#define SPINAND_CMD_PROG_RDM 0x84
+#define SPINAND_CMD_PROG 0x10
+#define SPINAND_CMD_ERASE_BLK 0xd8
+#define SPINAND_CMD_WR_ENABLE 0x06
+#define SPINAND_CMD_WR_DISABLE 0x04
+#define SPINAND_CMD_READ_ID 0x9f
+#define SPINAND_CMD_RESET 0xff
+#define SPINAND_CMD_READ_REG 0x0f
+#define SPINAND_CMD_WRITE_REG 0x1f
+
+#define SPINAND_CMD_READ_CACHE_X2 0x3b
+#define SPINAND_CMD_READ_CACHE_X4 0x6b
+#define SPINAND_CMD_READ_CACHE_DUAL 0xbb
+#define SPINAND_CMD_READ_CACHE_QUAD 0xeb
+
+#define SPINAND_CMD_PROG_LOAD_X4 0x32
+#define SPINAND_CMD_PROG_RDM_X4 0xC4 /*or 34*/
+
+/* feature registers */
+#define REG_BLOCK_LOCK 0xa0
+#define REG_OTP 0xb0
+#define REG_STATUS 0xc0/* timing */
+
+/* status */
+#define STATUS_OIP_MASK 0x01
+#define STATUS_READY (0 << 0)
+#define STATUS_BUSY (1 << 0)
+
+#define STATUS_E_FAIL_MASK 0x04
+#define STATUS_E_FAIL (1 << 2)
+
+#define STATUS_P_FAIL_MASK 0x08
+#define STATUS_P_FAIL (1 << 3)
+
+/*OTP register defines*/
+#define OTP_ECC_MASK 0X10
+#define OTP_ECC_ENABLE (1 << 4)
+#define OTP_ENABLE (1 << 6)
+#define OTP_LOCK (1 << 7)
+#define QE_ENABLE (1 << 0)
+
+
+/* block lock */
+#define BL_ALL_LOCKED 0x38
+#define BL_1_2_LOCKED 0x30
+#define BL_1_4_LOCKED 0x28
+#define BL_1_8_LOCKED 0x20
+#define BL_1_16_LOCKED 0x18
+#define BL_1_32_LOCKED 0x10
+#define BL_1_64_LOCKED 0x08
+#define BL_ALL_UNLOCKED 0
+
+#define SPI_NAND_ECC_SHIFT 4
+
+#define SPI_NAND_MT29F_ECC_MASK 3
+#define SPI_NAND_MT29F_ECC_CORRECTED 1
+#define SPI_NAND_MT29F_ECC_UNCORR 2
+#define SPI_NAND_MT29F_ECC_RESERVED 3
+#define SPI_NAND_MT29F_ECC_SHIFT 4
+
+#define SPI_NAND_GD5F_ECC_MASK 7
+#define SPI_NAND_GD5F_ECC_UNCORR 7
+#define SPI_NAND_GD5F_ECC_SHIFT 4
+
+struct spi_nand_onfi_params {
+ /* rev info and features block */
+ /* 'O' 'N' 'F' 'I' */
+ u8 sig[4]; /*0-3*/
+ __le16 revision; /*4-5*/
+ __le16 features; /*6-7*/
+ __le16 opt_cmd; /*8-9*/
+ u8 reserved0[22]; /*10-31*/
+
+ /* manufacturer information block */
+ char manufacturer[12]; /*32-43*/
+ char model[20]; /*44-63*/
+ u8 mfr_id; /*64*/
+ __le16 date_code; /*65-66*/
+ u8 reserved1[13]; /*67-79*/
+
+ /* memory organization block */
+ __le32 byte_per_page; /*80-83*/
+ __le16 spare_bytes_per_page; /*84*85*/
+ __le32 data_bytes_per_ppage; /*86-89*/
+ __le16 spare_bytes_per_ppage; /*90-91*/
+ __le32 pages_per_block; /*92-95*/
+ __le32 blocks_per_lun; /*96-99*/
+ u8 lun_count; /*100*/
+ u8 addr_cycles; /*101*/
+ u8 bits_per_cell; /*102*/
+ __le16 bb_per_lun; /*103-104*/
+ __le16 block_endurance; /*105-106*/
+ u8 guaranteed_good_blocks; /*107*/
+ __le16 guaranteed_block_endurance; /*108-109*/
+ u8 programs_per_page; /*110*/
+ u8 ppage_attr; /*111*/
+ u8 ecc_bits; /*112*/
+ u8 interleaved_bits; /*113*/
+ u8 interleaved_ops; /*114*/
+ u8 reserved2[13]; /*115-127*/
+
+ /* electrical parameter block */
+ u8 io_pin_capacitance_max; /*128*/
+ __le16 timing_mode; /*129-130*/
+ __le16 program_cache_timing_mode; /*131-132*/
+ __le16 t_prog; /*133-134*/
+ __le16 t_bers; /*135-136*/
+ __le16 t_r; /*137-138*/
+ __le16 t_ccs; /*139-140*/
+ u8 reserved3[23]; /*141-163*/
+
+ /* vendor */
+ __le16 vendor_specific_revision; /*164-165*/
+ u8 vendor_specific[88]; /*166-253*/
+
+ __le16 crc; /*254-255*/
+} __packed;
+
+#define ONFI_CRC_BASE 0x4F4E
+
+#define SPINAND_MAX_ID_LEN 4
+
+/**
+ * struct spi_nand_chip - SPI-NAND Private Flash Chip Data
+ * @chip_lock: [INTERN] protection lock
+ * @name: name of the chip
+ * @wq: [INTERN] wait queue to sleep on if a SPI-NAND operation
+ * is in progress used instead of the per chip wait queue
+ * when a hw controller is available.
+ * @mfr_id: [BOARDSPECIFIC] manufacture id
+ * @dev_id: [BOARDSPECIFIC] device id
+ * @state: [INTERN] the current state of the SPI-NAND device
+ * @spi: [INTERN] point to spi device structure
+ * @mtd: [INTERN] point to MTD device structure
+ * @reset: [REPLACEABLE] function to reset the device
+ * @read_id: [REPLACEABLE] read manufacture id and device id
+ * @load_page: [REPLACEABLE] load page from NAND to cache
+ * @read_cache: [REPLACEABLE] read data from cache
+ * @store_cache: [REPLACEABLE] write data to cache
+ * @write_page: [REPLACEABLE] program NAND with cache data
+ * @erase_block: [REPLACEABLE] erase a given block
+ * @waitfunc: [REPLACEABLE] wait for ready.
+ * @write_enable: [REPLACEABLE] set write enable latch
+ * @get_ecc_status: [REPLACEABLE] get ecc and bitflip status
+ * @enable_ecc: [REPLACEABLE] enable on-die ecc
+ * @disable_ecc: [REPLACEABLE] disable on-die ecc
+ * @buf: [INTERN] buffer for read/write
+ * @oobbuf: [INTERN] buffer for read/write oob
+ * @pagebuf: [INTERN] holds the pagenumber which is currently in
+ * data_buf.
+ * @pagebuf_bitflips: [INTERN] holds the bitflip count for the page which is
+ * currently in data_buf.
+ * @size: [INTERN] the size of chip
+ * @block_size: [INTERN] the size of eraseblock
+ * @page_size: [INTERN] the size of page
+ * @page_spare_size: [INTERN] the size of page oob size
+ * @block_shift: [INTERN] number of address bits in a eraseblock
+ * @page_shift: [INTERN] number of address bits in a page (column
+ * address bits).
+ * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
+ * @options: [BOARDSPECIFIC] various chip options. They can partly
+ * be set to inform nand_scan about special functionality.
+ * @ecc_strength_ds: [INTERN] ECC correctability from the datasheet.
+ * Minimum amount of bit errors per @ecc_step_ds guaranteed
+ * to be correctable. If unknown, set to zero.
+ * @ecc_step_ds: [INTERN] ECC step required by the @ecc_strength_ds,
+ * also from the datasheet. It is the recommended ECC step
+ * size, if known; if unknown, set to zero.
+ * @ecc_mask:
+ * @ecc_uncorr:
+ * @bits_per_cell: [INTERN] number of bits per cell. i.e., 1 means SLC.
+ * @ecclayout: [BOARDSPECIFIC] ECC layout control structure
+ * See the defines for further explanation.
+ * @bbt_options: [INTERN] bad block specific options. All options used
+ * here must come from bbm.h. By default, these options
+ * will be copied to the appropriate nand_bbt_descr's.
+ * @bbt: [INTERN] bad block table pointer
+ * @badblockpos: [INTERN] position of the bad block marker in the oob
+ * area.
+ * @bbt_td: [REPLACEABLE] bad block table descriptor for flash
+ * lookup.
+ * @bbt_md: [REPLACEABLE] bad block table mirror descriptor
+ * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial
+ * bad block scan.
+ * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is
+ * supported, 0 otherwise.
+ */
+struct spi_nand_chip {
+ spinlock_t chip_lock;
+ char *name;
+ wait_queue_head_t wq;
+ u8 dev_id_len;
+ u8 read_id_dummy;
+ u8 dev_id[SPINAND_MAX_ID_LEN];
+ flstate_t state;
+ struct spi_device *spi;
+ struct mtd_info *mtd;
+
+ int (*reset)(struct spi_nand_chip *chip);
+ int (*read_id)(struct spi_nand_chip *chip, u8 *id);
+ int (*load_page)(struct spi_nand_chip *chip, unsigned int page_addr);
+ int (*read_cache)(struct spi_nand_chip *chip, unsigned int page_addr,
+ unsigned int page_offset, size_t length, u8 *read_buf);
+ int (*store_cache)(struct spi_nand_chip *chip, unsigned int page_addr,
+ unsigned int page_offset, size_t length, u8 *write_buf);
+ int (*write_page)(struct spi_nand_chip *chip, unsigned int page_addr);
+ int (*erase_block)(struct spi_nand_chip *chip, u32 page_addr);
+ int (*waitfunc)(struct spi_nand_chip *chip, u8 *status);
+ int (*write_enable)(struct spi_nand_chip *chip);
+ void (*get_ecc_status)(struct spi_nand_chip *chip, unsigned int status,
+ unsigned int *corrected,
+ unsigned int *ecc_errors);
+ int (*enable_ecc)(struct spi_nand_chip *chip);
+ int (*disable_ecc)(struct spi_nand_chip *chip);
+ int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+ int (*set_qe)(struct spi_nand_chip *chip);
+
+ u8 *buf;
+ u8 *oobbuf;
+ int pagebuf;
+ u32 pagebuf_bitflips;
+ u64 size;
+ u32 block_size;
+ u16 page_size;
+ u16 page_spare_size;
+ u8 block_shift;
+ u8 page_shift;
+ u16 page_mask;
+ u32 options;
+ u16 ecc_strength_ds;
+ u16 ecc_step_ds;
+ u8 ecc_mask;
+ u8 ecc_uncorr;
+ u8 bits_per_cell;
+ struct nand_ecclayout *ecclayout;
+ u32 bbt_options;
+ u8 *bbt;
+ int badblockpos;
+ struct nand_bbt_descr *bbt_td;
+ struct nand_bbt_descr *bbt_md;
+ struct nand_bbt_descr *badblock_pattern;
+ struct spi_nand_onfi_params onfi_params;
+ u32 qe_addr;
+ u32 qe_flag;
+ u32 qe_mask;
+ u32 multi_wire_command_length;
+ u32 bitflip_threshold;
+};
+
+
+struct spi_nand_id_info{
+#define SPI_NAND_ID_NO_DUMMY (0xff)
+#define SPI_NAND_ID_DUMMY (0x00)
+ u8 id_addr;
+ u8 id_len;
+};
+
+struct spi_nand_flash {
+ char *name;
+ struct spi_nand_id_info id_info;
+ u8 dev_id[SPINAND_MAX_ID_LEN];
+ u32 page_size;
+ u32 page_spare_size;
+ u32 pages_per_blk;
+ u32 blks_per_chip;
+ u32 options;
+ u8 ecc_mask;
+ u8 ecc_uncorr;
+ struct nand_ecclayout *ecc_layout;
+ u32 qe_addr;
+ u32 qe_flag;
+ u32 qe_mask;
+ u32 multi_wire_command_length;
+ u32 bbt_options;
+ u32 bitflip_threshold;
+};
+
+struct spi_nand_cmd {
+ u8 cmd;
+ u32 n_addr; /* Number of address */
+ u8 addr[4]; /* Reg Offset */
+ u32 n_tx; /* Number of tx bytes */
+ u8 *tx_buf; /* Tx buf */
+ u8 tx_nbits;
+ u32 n_rx; /* Number of rx bytes */
+ u8 *rx_buf; /* Rx buf */
+ u8 rx_nbits;
+};
+
+#define SPI_NAND_INFO(nm, mid, did, pagesz, sparesz, pg_per_blk,\
+ blk_per_chip, opts) \
+ { .name = (nm), .mfr_id = (mid), .dev_id = (did),\
+ .page_size = (pagesz), .page_spare_size = (sparesz),\
+ .pages_per_blk = (pg_per_blk), .blks_per_chip = (blk_per_chip),\
+ .options = (opts) }
+
+#define SPINAND_NEED_PLANE_SELECT (1 << 0)
+#define FIRST_DUMMY_BYTE (1 << 1)
+
+
+
+#define SPINAND_MFR_MICRON 0x2C
+#define SPINAND_MFR_GIGADEVICE 0xC8
+
+int spi_nand_send_cmd(struct spi_device *spi, struct spi_nand_cmd *cmd);
+int spi_nand_read_from_cache(struct spi_nand_chip *chip,
+ u32 page_addr, u32 column, size_t len, u8 *rbuf);
+int spi_nand_read_from_cache_snor_protocol(struct spi_nand_chip *chip,
+ u32 page_addr, u32 column, size_t len, u8 *rbuf);
+int spi_nand_scan_ident(struct mtd_info *mtd);
+int spi_nand_scan_tail(struct mtd_info *mtd);
+int spi_nand_scan_ident_release(struct mtd_info *mtd);
+int spi_nand_scan_tail_release(struct mtd_info *mtd);
+int spi_nand_release(struct mtd_info *mtd);
+int __spi_nand_erase(struct mtd_info *mtd, struct erase_info *einfo,
+ int allowbbt);
+int spi_nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
+int spi_nand_default_bbt(struct mtd_info *mtd);
+int spi_nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
+#endif /* __LINUX_MTD_SPI_NAND_H */
+
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index c425c7b4..18ab3e4c 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -28,7 +28,13 @@
#define SNOR_MFR_SPANSION CFI_MFR_AMD
#define SNOR_MFR_SST CFI_MFR_SST
#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */
-
+#define SNOR_MFR_XMC 0x20
+#define SNOR_MFR_EON 0x1c
+#define SNOR_MFR_FM 0xa1
+#define SNOR_MFR_NM 0x52
+#define SNOR_MFR_XTX 0x0B
+#define SNOR_MFR_ZB 0x5e
+#define SNOR_MFR_BY 0x68
/*
* Note on opcode nomenclature: some opcodes have a format like
* SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
@@ -100,6 +106,10 @@
/* Configuration Register bits. */
#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */
+/* Used for GD flash only. */
+#define SPINOR_OP_GD_WR2 0x31 /* GD write status2 */
+
+
enum read_mode {
SPI_NOR_NORMAL = 0,
SPI_NOR_FAST,
@@ -157,6 +167,7 @@ struct spi_nor {
struct mtd_info mtd;
struct mutex lock;
struct device *dev;
+ struct flash_info *info;
u32 page_size;
u8 addr_width;
u8 erase_opcode;
@@ -172,6 +183,7 @@ struct spi_nor {
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
+ void (*scan_delay)(struct spi_nor *nor);
ssize_t (*read)(struct spi_nor *nor, loff_t from,
size_t len, u_char *read_buf);
@@ -186,6 +198,47 @@ struct spi_nor {
void *priv;
};
+#define SPI_NOR_MAX_ID_LEN 6
+#define SPI_NOR_MAX_ADDR_WIDTH 4
+
+struct flash_info {
+ char *name;
+
+ /*
+ * This array stores the ID bytes.
+ * The first three bytes are the JEDIC ID.
+ * JEDEC ID zero means "no ID" (mostly older chips).
+ */
+ u8 id[SPI_NOR_MAX_ID_LEN];
+ u8 id_len;
+
+ /* The size listed here is what works with SPINOR_OP_SE, which isn't
+ * necessarily called a "sector" by the vendor.
+ */
+ unsigned int sector_size;
+ u16 n_sectors;
+
+ u16 page_size;
+ u16 addr_width;
+
+ u16 flags;
+#define SECT_4K BIT(0) /* SPINOR_OP_BE_4K works uniformly */
+#define SPI_NOR_NO_ERASE BIT(1) /* No erase command needed */
+#define SST_WRITE BIT(2) /* use SST byte programming */
+#define SPI_NOR_NO_FR BIT(3) /* Can't do fastread */
+#define SECT_4K_PMC BIT(4)/* SPINOR_OP_BE_4K_PMC works uniformly */
+#define SPI_NOR_DUAL_READ BIT(5) /* Flash supports Dual Read */
+#define SPI_NOR_QUAD_READ BIT(6) /* Flash supports Quad Read */
+#define USE_FSR BIT(7) /* use flag status register */
+#define SPI_NOR_HAS_LOCK BIT(8) /* Flash supports lock/unlock via SR */
+#define SPI_NOR_HAS_TB BIT(9) /*
+ * Flash SR has Top/Bottom (TB) protect
+ * bit. Must be used with
+ * SPI_NOR_HAS_LOCK.
+ */
+ u32 max_speed_hz;
+};
+
static inline void spi_nor_set_flash_node(struct spi_nor *nor,
struct device_node *np)
{
@@ -212,5 +265,6 @@ static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor)
* Return: 0 for success, others for failure.
*/
int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode);
+void spi_nor_restore(struct spi_nor *nor);
#endif
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 47c7f5b8..bea4b0e0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2075,7 +2075,12 @@ static inline void *netdev_priv(const struct net_device *dev)
/* Default NAPI poll() weight
* Device drivers are strongly advised to not use bigger value
*/
+#ifdef CONFIG_TINY_KERNEL
+#define NAPI_POLL_WEIGHT 32
+#else
#define NAPI_POLL_WEIGHT 64
+#endif
+
/**
* netif_napi_add - initialize a NAPI context
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 867110c9..551ea7e6 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -426,6 +426,7 @@ struct phy_device {
u8 mdix;
void (*adjust_link)(struct net_device *dev);
+ u32 link_down_times;
};
#define to_phy_device(d) container_of(to_mdio_device(d), \
struct phy_device, mdio)
@@ -588,7 +589,16 @@ struct phy_driver {
void (*get_strings)(struct phy_device *dev, u8 *data);
void (*get_stats)(struct phy_device *dev,
struct ethtool_stats *stats, u64 *data);
+ int (*no_link_timeout_process)(struct phy_device *dev);
};
+
+static inline void bind_no_link_process(struct phy_driver *drv,
+int (*handler)(struct phy_device *))
+{
+ if (drv)
+ drv->no_link_timeout_process = handler;
+}
+
#define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
struct phy_driver, mdiodrv)
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 98c2a7c7..965936ab 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -227,6 +227,23 @@ static inline void platform_set_drvdata(struct platform_device *pdev,
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
+#ifdef CONFIG_DEFERRED_INIICALLS
+#define deferred_module_driver(__driver, __register, __unregister, ...) \
+static int __init __driver##_init(void) \
+{ \
+ return __register(&(__driver), ##__VA_ARGS__); \
+} \
+deferred_module_init(__driver##_init); \
+static void __exit __driver##_exit(void) \
+{ \
+ __unregister(&(__driver), ##__VA_ARGS__); \
+} \
+module_exit(__driver##_exit);
+
+#define deferred_module_platform_driver(__platform_driver) \
+ deferred_module_driver(__platform_driver, platform_driver_register, \
+ platform_driver_unregister)
+#endif
/* builtin_platform_driver() - Helper macro for builtin drivers that
* don't do anything special in driver init. This eliminates some
diff --git a/include/linux/sched.h b/include/linux/sched.h
index f4a551a5..577eb385 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1519,7 +1519,10 @@ struct task_struct {
#ifdef CONFIG_CGROUP_SCHED
struct task_group *sched_task_group;
#endif
+
+#ifdef CONFIG_SCHED_DL
struct sched_dl_entity dl;
+#endif
#ifdef CONFIG_PREEMPT_NOTIFIERS
/* list of struct preempt_notifier: */
@@ -3544,6 +3547,44 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
+extern int sched_dl_global_validate(void);
+extern void sched_dl_do_global(void);
+extern int sched_dl_overflow(struct task_struct *p, int policy,
+ const struct sched_attr *attr);
+extern void __setparam_dl(struct task_struct *p, const struct sched_attr *attr);
+extern void __getparam_dl(struct task_struct *p, struct sched_attr *attr);
+extern bool __checkparam_dl(const struct sched_attr *attr);
+extern void __dl_clear_params(struct task_struct *p);
+extern bool dl_param_changed(struct task_struct *p,
+ const struct sched_attr *attr);
+extern int dl_task_can_attach(struct task_struct *p,
+ const struct cpumask *cs_cpus_allowed);
+extern int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur,
+ const struct cpumask *trial);
+extern struct dl_bandwidth def_dl_bandwidth;
+
+struct dl_rq;
+struct dl_bw;
+
+#ifdef CONFIG_SCHED_DL
+#define dl_nr_running(rq) ((rq)->dl.dl_nr_running)
+#define dl_boosted(tsk) ((tsk)->dl.dl_boosted)
+extern bool dl_cpu_busy(unsigned int cpu);
+extern void init_sched_dl_class(void);
+extern void init_dl_bandwidth(struct dl_bandwidth *dl_b,
+ u64 period, u64 runtime);
+extern void init_dl_rq(struct dl_rq *dl_rq);
+extern void init_dl_bw(struct dl_bw *dl_b);
+#else
+#define dl_nr_running(rq) 0
+#define dl_boosted(tsk) (*(int *)0)
+#define dl_cpu_busy(cpu) false
+#define init_dl_bw(dl_b) do { } while (0)
+#define init_sched_dl_class() do { } while (0)
+#define init_dl_bandwidth(...) do { } while (0)
+#define init_dl_rq(dl_rq) do { } while (0)
+#endif
+
#ifdef CONFIG_CGROUP_SCHED
extern struct task_group root_task_group;
#endif /* CONFIG_CGROUP_SCHED */
diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h
index 9089a2ae..2bb5ddca 100644
--- a/include/linux/sched/deadline.h
+++ b/include/linux/sched/deadline.h
@@ -11,7 +11,7 @@
static inline int dl_prio(int prio)
{
- if (unlikely(prio < MAX_DL_PRIO))
+ if (IS_ENABLED(CONFIG_SCHED_DL) && unlikely(prio < MAX_DL_PRIO))
return 1;
return 0;
}
@@ -26,4 +26,10 @@ static inline bool dl_time_before(u64 a, u64 b)
return (s64)(a - b) < 0;
}
+#ifdef CONFIG_SCHED_DL
+#define dl_deadline(tsk) ((tsk)->dl.deadline)
+#else
+#define dl_deadline(tsk) 0
+#endif
+
#endif /* _SCHED_DEADLINE_H */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index eb4f6456..195d79f9 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -408,6 +408,7 @@ void uart_unregister_driver(struct uart_driver *uart);
int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
int uart_match_port(struct uart_port *port1, struct uart_port *port2);
+void uart_port_lock_init(struct uart_port *port);
/*
* Power Management
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 4b743ac3..3ab2a161 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -141,6 +141,7 @@ struct spi_device {
struct device dev;
struct spi_master *master;
u32 max_speed_hz;
+ u32 sample_delay;
u8 chip_select;
u8 bits_per_word;
u16 mode;
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
new file mode 100644
index 00000000..9c4011e4
--- /dev/null
+++ b/include/linux/tee_drv.h
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __TEE_DRV_H
+#define __TEE_DRV_H
+
+#include <linux/types.h>
+#include <linux/idr.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/tee.h>
+
+/*
+ * The file describes the API provided by the generic TEE driver to the
+ * specific TEE driver.
+ */
+
+#define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */
+#define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */
+#define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */
+#define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */
+#define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */
+#define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */
+
+struct device;
+struct tee_device;
+struct tee_shm;
+struct tee_shm_pool;
+
+/**
+ * struct tee_context - driver specific context on file pointer data
+ * @teedev: pointer to this drivers struct tee_device
+ * @list_shm: List of shared memory object owned by this context
+ * @data: driver specific context data, managed by the driver
+ * @refcount: reference counter for this structure
+ * @releasing: flag that indicates if context is being released right now.
+ * It is needed to break circular dependency on context during
+ * shared memory release.
+ */
+struct tee_context {
+ struct tee_device *teedev;
+ struct list_head list_shm;
+ void *data;
+ struct kref refcount;
+ bool releasing;
+};
+
+struct tee_param_memref {
+ size_t shm_offs;
+ size_t size;
+ struct tee_shm *shm;
+};
+
+struct tee_param_value {
+ u64 a;
+ u64 b;
+ u64 c;
+};
+
+struct tee_param {
+ u64 attr;
+ union {
+ struct tee_param_memref memref;
+ struct tee_param_value value;
+ } u;
+};
+
+/**
+ * struct tee_driver_ops - driver operations vtable
+ * @get_version: returns version of driver
+ * @open: called when the device file is opened
+ * @release: release this open file
+ * @open_session: open a new session
+ * @close_session: close a session
+ * @invoke_func: invoke a trusted function
+ * @cancel_req: request cancel of an ongoing invoke or open
+ * @supp_revc: called for supplicant to get a command
+ * @supp_send: called for supplicant to send a response
+ * @shm_register: register shared memory buffer in TEE
+ * @shm_unregister: unregister shared memory buffer in TEE
+ */
+struct tee_driver_ops {
+ void (*get_version)(struct tee_device *teedev,
+ struct tee_ioctl_version_data *vers);
+ int (*open)(struct tee_context *ctx);
+ void (*release)(struct tee_context *ctx);
+ int (*open_session)(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param);
+ int (*close_session)(struct tee_context *ctx, u32 session);
+ int (*invoke_func)(struct tee_context *ctx,
+ struct tee_ioctl_invoke_arg *arg,
+ struct tee_param *param);
+ int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session);
+ int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params,
+ struct tee_param *param);
+ int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params,
+ struct tee_param *param);
+ int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm,
+ struct page **pages, size_t num_pages,
+ unsigned long start);
+ int (*shm_unregister)(struct tee_context *ctx, struct tee_shm *shm);
+};
+
+/**
+ * struct tee_desc - Describes the TEE driver to the subsystem
+ * @name: name of driver
+ * @ops: driver operations vtable
+ * @owner: module providing the driver
+ * @flags: Extra properties of driver, defined by TEE_DESC_* below
+ */
+#define TEE_DESC_PRIVILEGED 0x1
+struct tee_desc {
+ const char *name;
+ const struct tee_driver_ops *ops;
+ struct module *owner;
+ u32 flags;
+};
+
+/**
+ * tee_device_alloc() - Allocate a new struct tee_device instance
+ * @teedesc: Descriptor for this driver
+ * @dev: Parent device for this device
+ * @pool: Shared memory pool, NULL if not used
+ * @driver_data: Private driver data for this device
+ *
+ * Allocates a new struct tee_device instance. The device is
+ * removed by tee_device_unregister().
+ *
+ * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure
+ */
+struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
+ struct device *dev,
+ struct tee_shm_pool *pool,
+ void *driver_data);
+
+/**
+ * tee_device_register() - Registers a TEE device
+ * @teedev: Device to register
+ *
+ * tee_device_unregister() need to be called to remove the @teedev if
+ * this function fails.
+ *
+ * @returns < 0 on failure
+ */
+int tee_device_register(struct tee_device *teedev);
+
+/**
+ * tee_device_unregister() - Removes a TEE device
+ * @teedev: Device to unregister
+ *
+ * This function should be called to remove the @teedev even if
+ * tee_device_register() hasn't been called yet. Does nothing if
+ * @teedev is NULL.
+ */
+void tee_device_unregister(struct tee_device *teedev);
+
+/**
+ * struct tee_shm - shared memory object
+ * @teedev: device used to allocate the object
+ * @ctx: context using the object, if NULL the context is gone
+ * @link link element
+ * @paddr: physical address of the shared memory
+ * @kaddr: virtual address of the shared memory
+ * @size: size of shared memory
+ * @offset: offset of buffer in user space
+ * @pages: locked pages from userspace
+ * @num_pages: number of locked pages
+ * @dmabuf: dmabuf used to for exporting to user space
+ * @flags: defined by TEE_SHM_* in tee_drv.h
+ * @id: unique id of a shared memory object on this device
+ *
+ * This pool is only supposed to be accessed directly from the TEE
+ * subsystem and from drivers that implements their own shm pool manager.
+ */
+struct tee_shm {
+ struct tee_device *teedev;
+ struct tee_context *ctx;
+ struct list_head link;
+ phys_addr_t paddr;
+ void *kaddr;
+ size_t size;
+ unsigned int offset;
+ struct page **pages;
+ size_t num_pages;
+ struct dma_buf *dmabuf;
+ u32 flags;
+ int id;
+};
+
+/**
+ * struct tee_shm_pool_mgr - shared memory manager
+ * @ops: operations
+ * @private_data: private data for the shared memory manager
+ */
+struct tee_shm_pool_mgr {
+ const struct tee_shm_pool_mgr_ops *ops;
+ void *private_data;
+};
+
+/**
+ * struct tee_shm_pool_mgr_ops - shared memory pool manager operations
+ * @alloc: called when allocating shared memory
+ * @free: called when freeing shared memory
+ * @destroy_poolmgr: called when destroying the pool manager
+ */
+struct tee_shm_pool_mgr_ops {
+ int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
+ size_t size);
+ void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
+ void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr);
+};
+
+/**
+ * tee_shm_pool_alloc() - Create a shared memory pool from shm managers
+ * @priv_mgr: manager for driver private shared memory allocations
+ * @dmabuf_mgr: manager for dma-buf shared memory allocations
+ *
+ * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
+ * in @dmabuf, others will use the range provided by @priv.
+ *
+ * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
+ */
+struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
+ struct tee_shm_pool_mgr *dmabuf_mgr);
+
+/*
+ * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved
+ * memory
+ * @vaddr: Virtual address of start of pool
+ * @paddr: Physical address of start of pool
+ * @size: Size in bytes of the pool
+ *
+ * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure.
+ */
+struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr,
+ phys_addr_t paddr,
+ size_t size,
+ int min_alloc_order);
+
+/**
+ * tee_shm_pool_mgr_destroy() - Free a shared memory manager
+ */
+static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
+{
+ poolm->ops->destroy_poolmgr(poolm);
+}
+
+/**
+ * struct tee_shm_pool_mem_info - holds information needed to create a shared
+ * memory pool
+ * @vaddr: Virtual address of start of pool
+ * @paddr: Physical address of start of pool
+ * @size: Size in bytes of the pool
+ */
+struct tee_shm_pool_mem_info {
+ unsigned long vaddr;
+ phys_addr_t paddr;
+ size_t size;
+};
+
+/**
+ * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
+ * memory range
+ * @priv_info: Information for driver private shared memory pool
+ * @dmabuf_info: Information for dma-buf shared memory pool
+ *
+ * Start and end of pools will must be page aligned.
+ *
+ * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
+ * in @dmabuf, others will use the range provided by @priv.
+ *
+ * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
+ */
+struct tee_shm_pool *
+tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
+ struct tee_shm_pool_mem_info *dmabuf_info);
+
+/**
+ * tee_shm_pool_free() - Free a shared memory pool
+ * @pool: The shared memory pool to free
+ *
+ * The must be no remaining shared memory allocated from this pool when
+ * this function is called.
+ */
+void tee_shm_pool_free(struct tee_shm_pool *pool);
+
+/**
+ * tee_get_drvdata() - Return driver_data pointer
+ * @returns the driver_data pointer supplied to tee_register().
+ */
+void *tee_get_drvdata(struct tee_device *teedev);
+
+/**
+ * tee_shm_alloc() - Allocate shared memory
+ * @ctx: Context that allocates the shared memory
+ * @size: Requested size of shared memory
+ * @flags: Flags setting properties for the requested shared memory.
+ *
+ * Memory allocated as global shared memory is automatically freed when the
+ * TEE file pointer is closed. The @flags field uses the bits defined by
+ * TEE_SHM_* above. TEE_SHM_MAPPED must currently always be set. If
+ * TEE_SHM_DMA_BUF global shared memory will be allocated and associated
+ * with a dma-buf handle, else driver private memory.
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
+
+/**
+ * tee_shm_priv_alloc() - Allocate shared memory privately
+ * @dev: Device that allocates the shared memory
+ * @size: Requested size of shared memory
+ *
+ * Allocates shared memory buffer that is not associated with any client
+ * context. Such buffers are owned by TEE driver and used for internal calls.
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size);
+
+/**
+ * tee_shm_register() - Register shared memory buffer
+ * @ctx: Context that registers the shared memory
+ * @addr: Address is userspace of the shared buffer
+ * @length: Length of the shared buffer
+ * @flags: Flags setting properties for the requested shared memory.
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
+ size_t length, u32 flags);
+
+/**
+ * tee_shm_register_fd() - Register shared memory from file descriptor
+ *
+ * @ctx: Context that allocates the shared memory
+ * @fd: shared memory file descriptor reference.
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd);
+
+/**
+ * tee_shm_is_registered() - Check if shared memory object in registered in TEE
+ * @shm: Shared memory handle
+ * @returns true if object is registered in TEE
+ */
+static inline bool tee_shm_is_registered(struct tee_shm *shm)
+{
+ return shm && (shm->flags & TEE_SHM_REGISTER);
+}
+
+/**
+ * tee_shm_free() - Free shared memory
+ * @shm: Handle to shared memory to free
+ */
+void tee_shm_free(struct tee_shm *shm);
+
+/**
+ * tee_shm_put() - Decrease reference count on a shared memory handle
+ * @shm: Shared memory handle
+ */
+void tee_shm_put(struct tee_shm *shm);
+
+/**
+ * tee_shm_va2pa() - Get physical address of a virtual address
+ * @shm: Shared memory handle
+ * @va: Virtual address to tranlsate
+ * @pa: Returned physical address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa);
+
+/**
+ * tee_shm_pa2va() - Get virtual address of a physical address
+ * @shm: Shared memory handle
+ * @pa: Physical address to tranlsate
+ * @va: Returned virtual address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va);
+
+/**
+ * tee_shm_get_va() - Get virtual address of a shared memory plus an offset
+ * @shm: Shared memory handle
+ * @offs: Offset from start of this shared memory
+ * @returns virtual address of the shared memory + offs if offs is within
+ * the bounds of this shared memory, else an ERR_PTR
+ */
+void *tee_shm_get_va(struct tee_shm *shm, size_t offs);
+
+/**
+ * tee_shm_get_pa() - Get physical address of a shared memory plus an offset
+ * @shm: Shared memory handle
+ * @offs: Offset from start of this shared memory
+ * @pa: Physical address to return
+ * @returns 0 if offs is within the bounds of this shared memory, else an
+ * error code.
+ */
+int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa);
+
+/**
+ * tee_shm_get_size() - Get size of shared memory buffer
+ * @shm: Shared memory handle
+ * @returns size of shared memory
+ */
+static inline size_t tee_shm_get_size(struct tee_shm *shm)
+{
+ return shm->size;
+}
+
+/**
+ * tee_shm_get_pages() - Get list of pages that hold shared buffer
+ * @shm: Shared memory handle
+ * @num_pages: Number of pages will be stored there
+ * @returns pointer to pages array
+ */
+static inline struct page **tee_shm_get_pages(struct tee_shm *shm,
+ size_t *num_pages)
+{
+ *num_pages = shm->num_pages;
+ return shm->pages;
+}
+
+/**
+ * tee_shm_get_page_offset() - Get shared buffer offset from page start
+ * @shm: Shared memory handle
+ * @returns page offset of shared buffer
+ */
+static inline size_t tee_shm_get_page_offset(struct tee_shm *shm)
+{
+ return shm->offset;
+}
+
+/**
+ * tee_shm_get_id() - Get id of a shared memory object
+ * @shm: Shared memory handle
+ * @returns id
+ */
+static inline int tee_shm_get_id(struct tee_shm *shm)
+{
+ return shm->id;
+}
+
+/**
+ * tee_shm_get_from_id() - Find shared memory object and increase reference
+ * count
+ * @ctx: Context owning the shared memory
+ * @id: Id of shared memory object
+ * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure
+ */
+struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id);
+
+/**
+ * tee_client_open_context() - Open a TEE context
+ * @start: if not NULL, continue search after this context
+ * @match: function to check TEE device
+ * @data: data for match function
+ * @vers: if not NULL, version data of TEE device of the context returned
+ *
+ * This function does an operation similar to open("/dev/teeX") in user space.
+ * A returned context must be released with tee_client_close_context().
+ *
+ * Returns a TEE context of the first TEE device matched by the match()
+ * callback or an ERR_PTR.
+ */
+struct tee_context *
+tee_client_open_context(struct tee_context *start,
+ int (*match)(struct tee_ioctl_version_data *,
+ const void *),
+ const void *data, struct tee_ioctl_version_data *vers);
+
+/**
+ * tee_client_close_context() - Close a TEE context
+ * @ctx: TEE context to close
+ *
+ * Note that all sessions previously opened with this context will be
+ * closed when this function is called.
+ */
+void tee_client_close_context(struct tee_context *ctx);
+
+/**
+ * tee_client_get_version() - Query version of TEE
+ * @ctx: TEE context to TEE to query
+ * @vers: Pointer to version data
+ */
+void tee_client_get_version(struct tee_context *ctx,
+ struct tee_ioctl_version_data *vers);
+
+/**
+ * tee_client_open_session() - Open a session to a Trusted Application
+ * @ctx: TEE context
+ * @arg: Open session arguments, see description of
+ * struct tee_ioctl_open_session_arg
+ * @param: Parameters passed to the Trusted Application
+ *
+ * Returns < 0 on error else see @arg->ret for result. If @arg->ret
+ * is TEEC_SUCCESS the session identifier is available in @arg->session.
+ */
+int tee_client_open_session(struct tee_context *ctx,
+ struct tee_ioctl_open_session_arg *arg,
+ struct tee_param *param);
+
+/**
+ * tee_client_close_session() - Close a session to a Trusted Application
+ * @ctx: TEE Context
+ * @session: Session id
+ *
+ * Return < 0 on error else 0, regardless the session will not be
+ * valid after this function has returned.
+ */
+int tee_client_close_session(struct tee_context *ctx, u32 session);
+
+/**
+ * tee_client_invoke_func() - Invoke a function in a Trusted Application
+ * @ctx: TEE Context
+ * @arg: Invoke arguments, see description of
+ * struct tee_ioctl_invoke_arg
+ * @param: Parameters passed to the Trusted Application
+ *
+ * Returns < 0 on error else see @arg->ret for result.
+ */
+int tee_client_invoke_func(struct tee_context *ctx,
+ struct tee_ioctl_invoke_arg *arg,
+ struct tee_param *param);
+
+static inline bool tee_param_is_memref(struct tee_param *param)
+{
+ switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+ case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#endif /*__TEE_DRV_H*/
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 39c25dbe..34916f90 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -150,12 +150,23 @@ extern unsigned long tick_nsec; /* SHIFTED_HZ period (nsec) */
#define NTP_INTERVAL_FREQ (HZ)
#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
-
+#ifdef CONFIG_NTP
extern int do_adjtimex(struct timex *);
extern void hardpps(const struct timespec64 *, const struct timespec64 *);
+void ntp_notify_cmos_timer(void);
+#else
+static inline int do_adjtimex(struct timex *txc)
+{
+ return 0;
+}
+static inline void hardpps(const struct timespec *ts1,
+ const struct timespec *ts2)
+{}
+static inline void ntp_notify_cmos_timer(void)
+{}
+#endif
int read_current_timer(unsigned long *timer_val);
-void ntp_notify_cmos_timer(void);
/* The clock frequency of the i8253/i8254 PIT */
#define PIT_TICK_RATE 1193182ul
diff --git a/include/linux/tty.h b/include/linux/tty.h
index fe1b8623..e6b5ee66 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -384,7 +384,6 @@ static inline bool tty_throttled(struct tty_struct *tty)
}
#ifdef CONFIG_TTY
-extern void console_init(void);
extern void tty_kref_put(struct tty_struct *tty);
extern struct pid *tty_get_pgrp(struct tty_struct *tty);
extern void tty_vhangup_self(void);
@@ -398,8 +397,6 @@ extern const char *tty_name(const struct tty_struct *tty);
extern int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
extern void tty_ldisc_unlock(struct tty_struct *tty);
#else
-static inline void console_init(void)
-{ }
static inline void tty_kref_put(struct tty_struct *tty)
{ }
static inline struct pid *tty_get_pgrp(struct tty_struct *tty)
@@ -664,7 +661,11 @@ extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p,
/* n_tty.c */
extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
+#ifdef CONFIG_TTY
extern void __init n_tty_init(void);
+#else
+static inline void n_tty_init(void) { }
+#endif
/* tty_audit.c */
#ifdef CONFIG_AUDIT
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index d43837f2..941b10ca 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -14,6 +14,7 @@ extern void tty_flip_buffer_push(struct tty_port *port);
void tty_schedule_flip(struct tty_port *port);
int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag);
+#ifndef CONFIG_MINITTY_SERIAL
static inline int tty_insert_flip_char(struct tty_port *port,
unsigned char ch, char flag)
{
@@ -35,6 +36,12 @@ static inline int tty_insert_flip_string(struct tty_port *port,
{
return tty_insert_flip_string_fixed_flag(port, chars, TTY_NORMAL, size);
}
+#else
+extern int tty_insert_flip_char(struct tty_port *port, unsigned char ch,
+ char flag);
+extern int tty_insert_flip_string(struct tty_port *port,
+ const unsigned char *chars, size_t size);
+#endif
extern void tty_buffer_lock_exclusive(struct tty_port *port);
extern void tty_buffer_unlock_exclusive(struct tty_port *port);
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 667d2045..43dd6908 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -51,8 +51,7 @@
#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
/* big enough to hold our biggest descriptor */
-#define USB_COMP_EP0_BUFSIZ 1024
-
+#define USB_COMP_EP0_BUFSIZ 2048
/* OS feature descriptor length <= 4kB */
#define USB_COMP_EP0_OS_DESC_BUFSIZ 4096
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 67929df8..6ac9a4a7 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -128,4 +128,6 @@ enum usb_dr_mode {
*/
extern enum usb_dr_mode usb_get_dr_mode(struct device *dev);
+extern u32 usb_get_vbus_pwren_gpio(struct device *dev);
+
#endif /* __LINUX_USB_OTG_H */
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index fde75507..543be86c 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -80,6 +80,7 @@ struct usbnet {
# define EVENT_LINK_CHANGE 11
# define EVENT_SET_RX_MODE 12
# define EVENT_NO_IP_ALIGN 13
+ struct delayed_work status_work;
};
static inline struct usb_driver *driver_of(struct usb_interface *intf)
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index f2acd2fd..17671174 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -28,13 +28,42 @@ struct af_alg_iv {
__u8 iv[0];
};
+#define MAX_EX_KEY_MAP_SIZE 8
+struct ex_key_map {
+ __u32 crypto_key_no;
+ __u32 ex_mem_entry;
+};
+
+struct ex_key_map_para {
+ __u32 map_size;
+ struct ex_key_map map[MAX_EX_KEY_MAP_SIZE];
+};
+
+struct crypto_adv_info {
+ struct ex_key_map_para ex_key_para;
+};
+
+struct af_alg_usr_def {
+#define CRYPTO_CPU_SET_KEY (1<<0)
+#define CRYPTO_EX_MEM_SET_KEY (1<<1)
+#define CRYPTO_EX_MEM_INDEP_POWER (1<<2)
+/*bit 8~ex mem bit field..*/
+#define CRYPTO_EX_MEM_SWITCH_KEY (1<<8)
+/*if set ex mem set switch key..then parse below..*/
+#define CRYPTO_EX_MEM_4_ENTRY_1_KEY (1<<9)
+ __u32 mode;
+/*if key_flag set efuse...then parse the para below...*/
+ struct crypto_adv_info adv;
+};
+
+
/* Socket options */
#define ALG_SET_KEY 1
#define ALG_SET_IV 2
#define ALG_SET_OP 3
#define ALG_SET_AEAD_ASSOCLEN 4
#define ALG_SET_AEAD_AUTHSIZE 5
-
+#define ALG_USR_DEF 8
/* Operations */
#define ALG_OP_DECRYPT 0
#define ALG_OP_ENCRYPT 1
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 99dbed8a..44004147 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -270,4 +270,6 @@
/* MPS2 UART */
#define PORT_MPS2UART 116
+#define PORT_FH 9999
+
#endif /* _UAPILINUX_SERIAL_CORE_H */
diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
new file mode 100644
index 00000000..08fb98f5
--- /dev/null
+++ b/include/uapi/linux/tee.h
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEE_H
+#define __TEE_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/*
+ * This file describes the API provided by a TEE driver to user space.
+ *
+ * Each TEE driver defines a TEE specific protocol which is used for the
+ * data passed back and forth using TEE_IOC_CMD.
+ */
+
+/* Helpers to make the ioctl defines */
+#define TEE_IOC_MAGIC 0xa4
+#define TEE_IOC_BASE 0
+
+/* Flags relating to shared memory */
+#define TEE_IOCTL_SHM_MAPPED 0x1 /* memory mapped in normal world */
+#define TEE_IOCTL_SHM_DMA_BUF 0x2 /* dma-buf handle on shared memory */
+
+#define TEE_MAX_ARG_SIZE 1024
+
+#define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */
+#define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */
+#define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */
+
+/*
+ * TEE Implementation ID
+ */
+#define TEE_IMPL_ID_OPTEE 1
+
+/*
+ * OP-TEE specific capabilities
+ */
+#define TEE_OPTEE_CAP_TZ (1 << 0)
+
+/**
+ * struct tee_ioctl_version_data - TEE version
+ * @impl_id: [out] TEE implementation id
+ * @impl_caps: [out] Implementation specific capabilities
+ * @gen_caps: [out] Generic capabilities, defined by TEE_GEN_CAPS_* above
+ *
+ * Identifies the TEE implementation, @impl_id is one of TEE_IMPL_ID_* above.
+ * @impl_caps is implementation specific, for example TEE_OPTEE_CAP_*
+ * is valid when @impl_id == TEE_IMPL_ID_OPTEE.
+ */
+struct tee_ioctl_version_data {
+ __u32 impl_id;
+ __u32 impl_caps;
+ __u32 gen_caps;
+};
+
+/**
+ * TEE_IOC_VERSION - query version of TEE
+ *
+ * Takes a tee_ioctl_version_data struct and returns with the TEE version
+ * data filled in.
+ */
+#define TEE_IOC_VERSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 0, \
+ struct tee_ioctl_version_data)
+
+/**
+ * struct tee_ioctl_shm_alloc_data - Shared memory allocate argument
+ * @size: [in/out] Size of shared memory to allocate
+ * @flags: [in/out] Flags to/from allocation.
+ * @id: [out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_ALLOC below.
+ */
+struct tee_ioctl_shm_alloc_data {
+ __u64 size;
+ __u32 flags;
+ __s32 id;
+};
+
+/**
+ * TEE_IOC_SHM_ALLOC - allocate shared memory
+ *
+ * Allocates shared memory between the user space process and secure OS.
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The returned file descriptor is used to map the shared memory into user
+ * space. The shared memory is freed when the descriptor is closed and the
+ * memory is unmapped.
+ */
+#define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \
+ struct tee_ioctl_shm_alloc_data)
+
+/**
+ * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument
+ * @fd: [in] file descriptor identifying the shared memory
+ * @size: [out] Size of shared memory to allocate
+ * @flags: [in] Flags to/from allocation.
+ * @id: [out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_ALLOC below.
+ */
+struct tee_ioctl_shm_register_fd_data {
+ __s64 fd;
+ __u64 size;
+ __u32 flags;
+ __s32 id;
+} __aligned(8);
+
+/**
+ * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The returned file descriptor refers to the shared memory object in kernel
+ * land. The shared memory is freed when the descriptor is closed.
+ */
+#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \
+ struct tee_ioctl_shm_register_fd_data)
+
+/**
+ * struct tee_ioctl_buf_data - Variable sized buffer
+ * @buf_ptr: [in] A __user pointer to a buffer
+ * @buf_len: [in] Length of the buffer above
+ *
+ * Used as argument for TEE_IOC_OPEN_SESSION, TEE_IOC_INVOKE,
+ * TEE_IOC_SUPPL_RECV, and TEE_IOC_SUPPL_SEND below.
+ */
+struct tee_ioctl_buf_data {
+ __u64 buf_ptr;
+ __u64 buf_len;
+};
+
+/*
+ * Attributes for struct tee_ioctl_param, selects field in the union
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_NONE 0 /* parameter not used */
+
+/*
+ * These defines value parameters (struct tee_ioctl_param_value)
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT 1
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT 3 /* input and output */
+
+/*
+ * These defines shared memory reference parameters (struct
+ * tee_ioctl_param_memref)
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT 5
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT 6
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT 7 /* input and output */
+
+/*
+ * Mask for the type part of the attribute, leaves room for more types
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff
+
+/* Meta parameter carrying extra information about the message. */
+#define TEE_IOCTL_PARAM_ATTR_META 0x100
+
+/* Mask of all known attr bits */
+#define TEE_IOCTL_PARAM_ATTR_MASK \
+ (TEE_IOCTL_PARAM_ATTR_TYPE_MASK | TEE_IOCTL_PARAM_ATTR_META)
+
+/*
+ * Matches TEEC_LOGIN_* in GP TEE Client API
+ * Are only defined for GP compliant TEEs
+ */
+#define TEE_IOCTL_LOGIN_PUBLIC 0
+#define TEE_IOCTL_LOGIN_USER 1
+#define TEE_IOCTL_LOGIN_GROUP 2
+#define TEE_IOCTL_LOGIN_APPLICATION 4
+#define TEE_IOCTL_LOGIN_USER_APPLICATION 5
+#define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6
+
+/**
+ * struct tee_ioctl_param - parameter
+ * @attr: attributes
+ * @a: if a memref, offset into the shared memory object, else a value parameter
+ * @b: if a memref, size of the buffer, else a value parameter
+ * @c: if a memref, shared memory identifier, else a value parameter
+ *
+ * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in
+ * the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and
+ * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE
+ * indicates that none of the members are used.
+ *
+ * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an
+ * identifier representing the shared memory object. A memref can reference
+ * a part of a shared memory by specifying an offset (@a) and size (@b) of
+ * the object. To supply the entire shared memory object set the offset
+ * (@a) to 0 and size (@b) to the previously returned size of the object.
+ */
+struct tee_ioctl_param {
+ __u64 attr;
+ __u64 a;
+ __u64 b;
+ __u64 c;
+};
+
+#define TEE_IOCTL_UUID_LEN 16
+
+/**
+ * struct tee_ioctl_open_session_arg - Open session argument
+ * @uuid: [in] UUID of the Trusted Application
+ * @clnt_uuid: [in] UUID of client
+ * @clnt_login: [in] Login class of client, TEE_IOCTL_LOGIN_* above
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @session: [out] Session id
+ * @ret: [out] return value
+ * @ret_origin [out] origin of the return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_ioctl_open_session_arg {
+ __u8 uuid[TEE_IOCTL_UUID_LEN];
+ __u8 clnt_uuid[TEE_IOCTL_UUID_LEN];
+ __u32 clnt_login;
+ __u32 cancel_id;
+ __u32 session;
+ __u32 ret;
+ __u32 ret_origin;
+ __u32 num_params;
+ /* num_params tells the actual number of element in params */
+ struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_ioctl_open_session_arg followed by any array of struct
+ * tee_ioctl_param
+ */
+#define TEE_IOC_OPEN_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 2, \
+ struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted
+ * Application
+ * @func: [in] Trusted Application function, specific to the TA
+ * @session: [in] Session id
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @ret: [out] return value
+ * @ret_origin [out] origin of the return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_ioctl_invoke_arg {
+ __u32 func;
+ __u32 session;
+ __u32 cancel_id;
+ __u32 ret;
+ __u32 ret_origin;
+ __u32 num_params;
+ /* num_params tells the actual number of element in params */
+ struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_INVOKE - Invokes a function in a Trusted Application
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_invoke_func_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_INVOKE _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 3, \
+ struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_ioctl_cancel_arg - Cancels an open session or invoke ioctl
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @session: [in] Session id, if the session is opened, else set to 0
+ */
+struct tee_ioctl_cancel_arg {
+ __u32 cancel_id;
+ __u32 session;
+};
+
+/**
+ * TEE_IOC_CANCEL - Cancels an open session or invoke
+ */
+#define TEE_IOC_CANCEL _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 4, \
+ struct tee_ioctl_cancel_arg)
+
+/**
+ * struct tee_ioctl_close_session_arg - Closes an open session
+ * @session: [in] Session id
+ */
+struct tee_ioctl_close_session_arg {
+ __u32 session;
+};
+
+/**
+ * TEE_IOC_CLOSE_SESSION - Closes a session
+ */
+#define TEE_IOC_CLOSE_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 5, \
+ struct tee_ioctl_close_session_arg)
+
+/**
+ * struct tee_iocl_supp_recv_arg - Receive a request for a supplicant function
+ * @func: [in] supplicant function
+ * @num_params [in/out] number of parameters following this struct
+ *
+ * @num_params is the number of params that tee-supplicant has room to
+ * receive when input, @num_params is the number of actual params
+ * tee-supplicant receives when output.
+ */
+struct tee_iocl_supp_recv_arg {
+ __u32 func;
+ __u32 num_params;
+ /* num_params tells the actual number of element in params */
+ struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_iocl_supp_recv_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_SUPPL_RECV _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 6, \
+ struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_iocl_supp_send_arg - Send a response to a received request
+ * @ret: [out] return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_iocl_supp_send_arg {
+ __u32 ret;
+ __u32 num_params;
+ /* num_params tells the actual number of element in params */
+ struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_iocl_supp_send_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \
+ struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_ioctl_shm_register_data - Shared memory register argument
+ * @addr: [in] Start address of shared memory to register
+ * @length: [in/out] Length of shared memory to register
+ * @flags: [in/out] Flags to/from registration.
+ * @id: [out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_REGISTER below.
+ */
+struct tee_ioctl_shm_register_data {
+ __u64 addr;
+ __u64 length;
+ __u32 flags;
+ __s32 id;
+};
+
+/**
+ * TEE_IOC_SHM_REGISTER - Register shared memory argument
+ *
+ * Registers shared memory between the user space process and secure OS.
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The shared memory is unregisterred when the descriptor is closed.
+ */
+#define TEE_IOC_SHM_REGISTER _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 9, \
+ struct tee_ioctl_shm_register_data)
+/*
+ * Five syscalls are used when communicating with the TEE driver.
+ * open(): opens the device associated with the driver
+ * ioctl(): as described above operating on the file descriptor from open()
+ * close(): two cases
+ * - closes the device file descriptor
+ * - closes a file descriptor connected to allocated shared memory
+ * mmap(): maps shared memory into user space using information from struct
+ * tee_ioctl_shm_alloc_data
+ * munmap(): unmaps previously shared memory
+ */
+
+#endif /*__TEE_H*/
diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
index 69ab695f..a36d4688 100644
--- a/include/uapi/linux/usb/video.h
+++ b/include/uapi/linux/usb/video.h
@@ -16,6 +16,14 @@
#include <linux/types.h>
+/* identification number of Unit or Terminal */
+#define UVC_INTERFACE_ID 0
+#define UVC_CAMERAL_TERMINAL_ID 1
+#define UVC_PROCESSING_UNIT_ID 2
+#define UVC_H264_EXTENSION_UNIT_ID 3
+#define UVC_OUTPUT_TERMINAL_ID 4
+#define UVC_OUTPUT_TERMINAL2_ID 5
+
/* --------------------------------------------------------------------------
* UVC constants
*/
@@ -565,5 +573,26 @@ struct UVC_FRAME_MJPEG(n) { \
__u32 dwFrameInterval[n]; \
} __attribute__ ((packed))
+/* Frame Based Payload - 3.1.1. Frame Based Format Descriptor */
+struct uvc_format_frameBased {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFormatIndex;
+ __u8 bNumFrameDescriptors;
+ __u8 guidFormat[16];
+ __u8 bBitsPerPixel;
+ __u8 bDefaultFrameIndex;
+ __u8 bAspectRatioX;
+ __u8 bAspectRatioY;
+ __u8 bmInterfaceFlags;
+ __u8 bCopyProtect;
+ __u8 bVariableSize;
+} __attribute__((__packed__));
+
+#define UVC_DT_FORMAT_FRAMEBASED_SIZE 28
+
+#define UVC_DT_FRAME_FRAMEBASED_SIZE(n) (26+4*(n))
+
#endif /* __LINUX_USB_VIDEO_H */
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 7f34d3c6..2d4bf69f 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -511,6 +511,7 @@ struct v4l2_pix_format {
/* Luminance+Chrominance formats */
#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_YUY2 v4l2_fourcc('Y', 'U', 'Y', '2') /* 16 YUV 4:2:2 */
#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16 YUV 4:2:2 */
#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16 YUV 4:2:2 */
@@ -592,6 +593,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_DV v4l2_fourcc('d', 'v', 's', 'd') /* 1394 */
#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
#define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
+#define V4L2_PIX_FMT_H265 v4l2_fourcc('H', '2', '6', '5') /* H264 with start codes */
#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
#define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */
@@ -2259,7 +2261,7 @@ struct v4l2_create_buffers {
#define VIDIOC_G_JPEGCOMP _IOR('V', 61, struct v4l2_jpegcompression)
#define VIDIOC_S_JPEGCOMP _IOW('V', 62, struct v4l2_jpegcompression)
#define VIDIOC_QUERYSTD _IOR('V', 63, v4l2_std_id)
-#define VIDIOC_TRY_FMT _IOWR('V', 64, struct v4l2_format)
+#define VIDIOC_TRY_FMT _IOWR('V', 64, struct v4l2_format)
#define VIDIOC_ENUMAUDIO _IOWR('V', 65, struct v4l2_audio)
#define VIDIOC_ENUMAUDOUT _IOWR('V', 66, struct v4l2_audioout)
#define VIDIOC_G_PRIORITY _IOR('V', 67, __u32) /* enum v4l2_priority */
@@ -2280,8 +2282,8 @@ struct v4l2_create_buffers {
* Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
* You must be root to use these ioctls. Never use these in applications!
*/
-#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register)
-#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register)
+#define VIDIOC_DBG_S_REGISTER _IOW('V', 79, struct v4l2_dbg_register)
+#define VIDIOC_DBG_G_REGISTER _IOWR('V', 80, struct v4l2_dbg_register)
#define VIDIOC_S_HW_FREQ_SEEK _IOW('V', 82, struct v4l2_hw_freq_seek)
#define VIDIOC_S_DV_TIMINGS _IOWR('V', 87, struct v4l2_dv_timings)
diff --git a/init/Kconfig b/init/Kconfig
index b331feea..a1e9300e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,23 @@ config CROSS_COMPILE
need to set this unless you want the configured kernel build
directory to select the cross-compiler automatically.
+config TINY_KERNEL
+ bool "Fullhan Tiny Kernel Option"
+ default n
+ help
+ Fullhan Tiny Kernel Option.Use this option to optimize Linux Kernel.
+
+config NTP
+ bool "Enable NTP functionality and corresponding syscalls" if EXPERT
+ default y
+ help
+ This option enables NTP functionality and two syscalls used for
+ system clock synchronization: adjtimex and clock_adjtime syscalls.
+ If building an embedded system which doesn't need to synchronize its
+ system clock to an NTP server, you can disable this option to save
+ space.
+
+
config COMPILE_TEST
bool "Compile also drivers which will not load"
depends on !UML
@@ -209,6 +226,11 @@ config KERNEL_LZ4
is about 8% bigger than LZO. But the decompression speed is
faster than LZO.
+config KERNEL_NO_COMPRESS
+ bool "NONE"
+ help
+ Do not compress kernel image
+
endchoice
config DEFAULT_HOSTNAME
@@ -1119,6 +1141,7 @@ config CGROUP_HUGETLB
config CPUSETS
bool "Cpuset controller"
+ depends on SMP
help
This option will let you create and manage CPUSETs which
allow dynamically partitioning a system into sets of CPUs and
@@ -1247,7 +1270,15 @@ config SCHED_AUTOGROUP
of workloads isolates aggressive CPU burners (like build jobs) from
desktop applications. Task group autogeneration is currently based
upon task session.
-
+
+config SCHED_DL
+ bool "Deadline Task Scheduling" if EXPERT
+ default y
+ help
+ This adds the sched_dl scheduling class to the kernel providing
+ support for the SCHED_DEADLINE policy. You might want to disable
+ this to reduce the kernel size. If unsure say y.
+
config SYSFS_DEPRECATED
bool "Enable deprecated sysfs features to support old userspace tools"
depends on SYSFS
@@ -1341,6 +1372,33 @@ config CC_OPTIMIZE_FOR_SIZE
endchoice
+config HAVE_LD_DEAD_CODE_DATA_ELIMINATION
+ bool
+ help
+ This requires that the arch annotates or otherwise protects
+ its external entry points from being discarded. Linker scripts
+ must also merge .text.*, .data.*, and .bss.* correctly into
+ output sections. Care must be taken not to pull in unrelated
+ sections (e.g., '.text.init'). Typically '.' in section names
+ is used to distinguish them from label names / C identifiers.
+
+config LD_DEAD_CODE_DATA_ELIMINATION
+ bool "Dead code and data elimination (EXPERIMENTAL)"
+ depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
+ depends on EXPERT
+ help
+ Select this if the architecture wants to do dead code and
+ data elimination with the linker by compiling with
+ -ffunction-sections -fdata-sections, and linking with
+ --gc-sections.
+
+ This can reduce on disk and in-memory size of the kernel
+ code and static data, particularly for small configs and
+ on small systems. This has the possibility of introducing
+ silently broken kernel if the required annotations are not
+ present. This option is not well tested yet, so use at your
+ own risk.
+
config SYSCTL
bool
@@ -1380,7 +1438,6 @@ config BPF
menuconfig EXPERT
bool "Configure standard kernel features (expert users)"
# Unhide debug options, to make the on-by-default options visible
- select DEBUG_KERNEL
help
This option allows certain base kernel options and settings
to be disabled or tweaked. This is for specialized
@@ -2102,6 +2159,19 @@ config TRIM_UNUSED_KSYMS
If unsure, or if you need to build out-of-tree modules, say N.
+config UNUSED_KSYMS_WHITELIST
+ string "Whitelist of symbols to keep in ksymtab"
+ depends on TRIM_UNUSED_KSYMS
+ help
+ By default, all unused exported symbols will be un-exported from the
+ build when TRIM_UNUSED_KSYMS is selected.
+
+ UNUSED_KSYMS_WHITELIST allows to whitelist symbols that must be kept
+ exported at all times, even in absence of in-tree users. The value to
+ set here is the path to a text file containing the list of symbols,
+ one per line. The path can be absolute, or relative to the kernel
+ source tree.
+
endif # MODULES
config MODULES_TREE_LOOKUP
diff --git a/init/calibrate.c b/init/calibrate.c
index ce635dcc..a3d594cb 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -40,7 +40,8 @@ static unsigned long calibrate_delay_direct(void)
unsigned long good_timer_sum = 0;
unsigned long good_timer_count = 0;
unsigned long measured_times[MAX_DIRECT_CALIBRATION_RETRIES];
- int max = -1; /* index of measured_times with max/min values or not set */
+ /* index of measured_times with max/min values or not set */
+ int max = -1;
int min = -1;
int i;
@@ -95,7 +96,7 @@ static unsigned long calibrate_delay_direct(void)
* >= 12.5% apart, redo calibration.
*/
if (start >= post_end)
- printk(KERN_NOTICE "calibrate_delay_direct() ignoring "
+ pr_notice("calibrate_delay_direct() ignoring "
"timer_rate as we had a TSC wrap around"
" start=%lu >=post_end=%lu\n",
start, post_end);
@@ -134,13 +135,13 @@ static unsigned long calibrate_delay_direct(void)
good_timer_count = 0;
if ((measured_times[max] - estimate) <
(estimate - measured_times[min])) {
- printk(KERN_NOTICE "calibrate_delay_direct() dropping "
+ pr_notice("calibrate_delay_direct() dropping "
"min bogoMips estimate %d = %lu\n",
min, measured_times[min]);
measured_times[min] = 0;
min = max;
} else {
- printk(KERN_NOTICE "calibrate_delay_direct() dropping "
+ pr_notice("calibrate_delay_direct() dropping "
"max bogoMips estimate %d = %lu\n",
max, measured_times[max]);
measured_times[max] = 0;
@@ -247,6 +248,71 @@ static unsigned long calibrate_delay_converge(void)
return lpj;
}
+
+static unsigned long calibrate_delay_converge_in_arch(void)
+{
+ /* First stage - slowly accelerate to find initial bounds */
+ unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
+ int trials = 0, band = 0, trial_in_band = 0;
+
+ lpj = (1<<12);
+
+ /* wait for "start of" clock tick */
+ ticks = jiffies;
+ while (ticks == jiffies)
+ ; /* nothing */
+ /* Go .. */
+ ticks = jiffies;
+ do {
+ if (++trial_in_band == (1<<band)) {
+ ++band;
+ trial_in_band = 0;
+ }
+ __loop_delay(lpj * band);
+ trials += band;
+ } while (ticks == jiffies);
+ /*
+ * We overshot, so retreat to a clear underestimate. Then estimate
+ * the largest likely undershoot. This defines our chop bounds.
+ */
+ trials -= band;
+ loopadd_base = lpj * band;
+ lpj_base = lpj * trials;
+
+recalibrate:
+ lpj = lpj_base;
+ loopadd = loopadd_base;
+
+ /*
+ * Do a binary approximation to get lpj set to
+ * equal one clock (up to LPS_PREC bits)
+ */
+ chop_limit = lpj >> LPS_PREC;
+ while (loopadd > chop_limit) {
+ lpj += loopadd;
+ ticks = jiffies;
+ while (ticks == jiffies)
+ ; /* nothing */
+ ticks = jiffies;
+ __loop_delay(lpj);
+ if (jiffies != ticks) /* longer than 1 tick */
+ lpj -= loopadd;
+ loopadd >>= 1;
+ }
+ /*
+ * If we incremented every single time possible, presume we've
+ * massively underestimated initially, and retry with a higher
+ * start, and larger range. (Only seen on x86_64, due to SMIs)
+ */
+ if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
+ lpj_base = lpj;
+ loopadd_base <<= 2;
+ goto recalibrate;
+ }
+
+ return lpj;
+}
+
static DEFINE_PER_CPU(unsigned long, cpu_loops_per_jiffy) = { 0 };
/*
@@ -303,10 +369,13 @@ void calibrate_delay(void)
lpj = calibrate_delay_converge();
}
per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj;
+ /* Show True Bigomips when ARM Architecture Timer is used*/
+ unsigned long lpj_bigomips = calibrate_delay_converge_in_arch();
+
if (!printed)
pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
- lpj/(500000/HZ),
- (lpj/(5000/HZ)) % 100, lpj);
+ lpj_bigomips/(500000/HZ),
+ (lpj_bigomips/(5000/HZ)) % 100, lpj_bigomips);
loops_per_jiffy = lpj;
printed = true;
diff --git a/init/main.c b/init/main.c
index 4313772d..0396ee5c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -25,7 +25,7 @@
#include <linux/initrd.h>
#include <linux/bootmem.h>
#include <linux/acpi.h>
-#include <linux/tty.h>
+#include <linux/console.h>
#include <linux/percpu.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
@@ -946,7 +946,9 @@ static int __ref kernel_init(void *unused)
kernel_init_freeable();
/* need to finish all async __init code before freeing the memory */
async_synchronize_full();
+#ifndef CONFIG_DEFERRED_INIICALLS
free_initmem();
+#endif
mark_readonly();
system_state = SYSTEM_RUNNING;
numa_default_policy();
@@ -1048,3 +1050,36 @@ static noinline void __init kernel_init_freeable(void)
integrity_load_keys();
load_default_modules();
}
+
+#ifdef CONFIG_DEFERRED_INIICALLS
+extern initcall_t __deferred_initcall_start[], \
+ __deferred_initcall_end[];
+
+/* call deferred init routines */
+void do_deferred_initcalls(void)
+{
+ initcall_t *call;
+ static int already_run;
+
+ if (already_run) {
+ pr_err("do_deferred_initcalls() has already run\n");
+ return;
+ }
+
+ already_run = 1;
+
+ pr_info("Running do_deferred_initcalls()\n");
+
+ for (call = __deferred_initcall_start;
+ call < __deferred_initcall_end; call++) {
+#ifdef CONFIG_DEFERRED_INIICALLS_DEBUG
+ pr_err("deferred calling %pF\n", *call);
+#endif
+ do_one_initcall(*call);
+ }
+
+ flush_scheduled_work();
+
+ free_initmem();
+}
+#endif
diff --git a/kernel/compat.c b/kernel/compat.c
index 333d364b..f7b4b86c 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -30,7 +30,8 @@
#include <asm/uaccess.h>
-static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
+static int __maybe_unused compat_get_timex(struct timex *txc,
+ struct compat_timex __user *utp)
{
memset(txc, 0, sizeof(struct timex));
@@ -60,7 +61,8 @@ static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
return 0;
}
-static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
+static int __maybe_unused compat_put_timex(struct compat_timex __user *utp,
+ struct timex *txc)
{
if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
__put_user(txc->modes, &utp->modes) ||
@@ -770,7 +772,7 @@ COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
return -EFAULT;
return err;
}
-
+#ifdef CONFIG_NTP
COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
struct compat_timex __user *, utp)
{
@@ -793,7 +795,7 @@ COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
return ret;
}
-
+#endif
COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
struct compat_timespec __user *, tp)
{
@@ -1064,7 +1066,7 @@ COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
}
#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
-
+#ifdef CONFIG_NTP
COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
{
struct timex txc;
@@ -1082,7 +1084,7 @@ COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
return ret;
}
-
+#endif
#ifdef CONFIG_NUMA
COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
compat_uptr_t __user *, pages32,
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 77977f55..2c25b932 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -287,7 +287,11 @@ static int __init irq_sysfs_init(void)
return 0;
}
+#ifdef CONFIG_DEFERRED_INIICALLS_IRQ_SYSFS
+deferred_initcall(irq_sysfs_init);
+#else
postcore_initcall(irq_sysfs_init);
+#endif
#else /* !CONFIG_SYSFS */
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 196cc460..af6491e5 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -721,7 +721,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
* the values of the node being removed.
*/
waiter->prio = task->prio;
- waiter->deadline = task->dl.deadline;
+ waiter->deadline = dl_deadline(task);
rt_mutex_enqueue(lock, waiter);
@@ -997,7 +997,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
waiter->task = task;
waiter->lock = lock;
waiter->prio = task->prio;
- waiter->deadline = task->dl.deadline;
+ waiter->deadline = dl_deadline(task);
/* Get the top priority waiter on the lock */
if (rt_mutex_has_waiters(lock))
diff --git a/kernel/params.c b/kernel/params.c
index a6d6149c..6ddfb226 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -992,6 +992,7 @@ struct kobj_type module_ktype = {
.sysfs_ops = &module_sysfs_ops,
};
+
/*
* param_sysfs_init - wrapper for built-in params support
*/
@@ -1006,10 +1007,20 @@ static int __init param_sysfs_init(void)
module_sysfs_initialized = 1;
version_sysfs_builtin();
+#ifndef CONFIG_DEFERRED_INIICALLS_PARAM_SYSFS
param_sysfs_builtin();
+#endif
+ return 0;
+}
+#ifdef CONFIG_DEFERRED_INIICALLS_PARAM_SYSFS
+static int __init param_sysfs_init_later(void)
+{
+ param_sysfs_builtin();
return 0;
}
+deferred_initcall(param_sysfs_init_later);
+#endif
subsys_initcall(param_sysfs_init);
#endif /* CONFIG_SYSFS */
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index eb4f7177..91962908 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -3,7 +3,7 @@ ccflags-$(CONFIG_PM_DEBUG) := -DDEBUG
KASAN_SANITIZE_snapshot.o := n
-obj-y += qos.o
+obj-$(CONFIG_PM) += qos.o
obj-$(CONFIG_PM) += main.o
obj-$(CONFIG_VT_CONSOLE_SLEEP) += console.o
obj-$(CONFIG_FREEZER) += process.o
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ab6855a4..a410fca5 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2810,6 +2810,30 @@ int unregister_console(struct console *console)
}
EXPORT_SYMBOL(unregister_console);
+/*
+ * Initialize the console device. This is called *early*, so
+ * we can't necessarily depend on lots of kernel help here.
+ * Just do some early initializations, and do the complex setup
+ * later.
+ */
+void __init console_init(void)
+{
+ initcall_t *call;
+
+ /* Setup the default TTY line discipline. */
+ n_tty_init();
+
+ /*
+ * set up the console device so that later boot sequences can
+ * inform about problems etc..
+ */
+ call = __con_initcall_start;
+ while (call < __con_initcall_end) {
+ (*call)();
+ call++;
+ }
+}
+
/*
* Some boot consoles access data that is in the init section and which will
* be discarded after the initcalls have been run. To make sure that no code
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 5e59b832..181cad87 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -16,9 +16,10 @@ CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer
endif
obj-y += core.o loadavg.o clock.o cputime.o
-obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o
+obj-y += idle_task.o fair.o rt.o
obj-y += wait.o swait.o completion.o idle.o
-obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
+obj-$(CONFIG_SCHED_DL) += deadline.o $(if $(CONFIG_SMP),cpudeadline.o)
+obj-$(CONFIG_SMP) += cpupri.o stop_task.o
obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
obj-$(CONFIG_SCHEDSTATS) += stats.o
obj-$(CONFIG_SCHED_DEBUG) += debug.o
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 917be221..e4553880 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -637,7 +637,7 @@ bool sched_can_stop_tick(struct rq *rq)
int fifo_nr_running;
/* Deadline tasks, even if single, need the tick */
- if (rq->dl.dl_nr_running)
+ if (dl_nr_running(rq))
return false;
/*
@@ -838,36 +838,6 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
#endif
}
-void sched_set_stop_task(int cpu, struct task_struct *stop)
-{
- struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
- struct task_struct *old_stop = cpu_rq(cpu)->stop;
-
- if (stop) {
- /*
- * Make it appear like a SCHED_FIFO task, its something
- * userspace knows about and won't get confused about.
- *
- * Also, it will make PI more or less work without too
- * much confusion -- but then, stop work should not
- * rely on PI working anyway.
- */
- sched_setscheduler_nocheck(stop, SCHED_FIFO, &param);
-
- stop->sched_class = &stop_sched_class;
- }
-
- cpu_rq(cpu)->stop = stop;
-
- if (old_stop) {
- /*
- * Reset it back to a normal scheduling class so that
- * it can die in pieces.
- */
- old_stop->sched_class = &rt_sched_class;
- }
-}
-
/*
* __normal_prio - return the priority that is based on the static prio
*/
@@ -1628,6 +1598,36 @@ static void update_avg(u64 *avg, u64 sample)
*avg += diff >> 3;
}
+void sched_set_stop_task(int cpu, struct task_struct *stop)
+{
+ struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+ struct task_struct *old_stop = cpu_rq(cpu)->stop;
+
+ if (stop) {
+ /*
+ * Make it appear like a SCHED_FIFO task, its something
+ * userspace knows about and won't get confused about.
+ *
+ * Also, it will make PI more or less work without too
+ * much confusion -- but then, stop work should not
+ * rely on PI working anyway.
+ */
+ sched_setscheduler_nocheck(stop, SCHED_FIFO, &param);
+
+ stop->sched_class = &stop_sched_class;
+ }
+
+ cpu_rq(cpu)->stop = stop;
+
+ if (old_stop) {
+ /*
+ * Reset it back to a normal scheduling class so that
+ * it can die in pieces.
+ */
+ old_stop->sched_class = &rt_sched_class;
+ }
+}
+
#else
static inline int __set_cpus_allowed_ptr(struct task_struct *p,
@@ -2174,23 +2174,6 @@ int wake_up_state(struct task_struct *p, unsigned int state)
/*
* This function clears the sched_dl_entity static params.
- */
-void __dl_clear_params(struct task_struct *p)
-{
- struct sched_dl_entity *dl_se = &p->dl;
-
- dl_se->dl_runtime = 0;
- dl_se->dl_deadline = 0;
- dl_se->dl_period = 0;
- dl_se->flags = 0;
- dl_se->dl_bw = 0;
- dl_se->dl_density = 0;
-
- dl_se->dl_throttled = 0;
- dl_se->dl_yielded = 0;
-}
-
-/*
* Perform scheduler related setup for a newly forked process p.
* p is forked by current.
*
@@ -2217,9 +2200,11 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
memset(&p->se.statistics, 0, sizeof(p->se.statistics));
#endif
+#ifdef CONFIG_SCHED_DL
RB_CLEAR_NODE(&p->dl.rb_node);
init_dl_task_timer(&p->dl);
__dl_clear_params(p);
+#endif
INIT_LIST_HEAD(&p->rt.run_list);
p->rt.timeout = 0;
@@ -2469,90 +2454,6 @@ unsigned long to_ratio(u64 period, u64 runtime)
return div64_u64(runtime << 20, period);
}
-#ifdef CONFIG_SMP
-inline struct dl_bw *dl_bw_of(int i)
-{
- RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
- "sched RCU must be held");
- return &cpu_rq(i)->rd->dl_bw;
-}
-
-static inline int dl_bw_cpus(int i)
-{
- struct root_domain *rd = cpu_rq(i)->rd;
- int cpus = 0;
-
- RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
- "sched RCU must be held");
- for_each_cpu_and(i, rd->span, cpu_active_mask)
- cpus++;
-
- return cpus;
-}
-#else
-inline struct dl_bw *dl_bw_of(int i)
-{
- return &cpu_rq(i)->dl.dl_bw;
-}
-
-static inline int dl_bw_cpus(int i)
-{
- return 1;
-}
-#endif
-
-/*
- * We must be sure that accepting a new task (or allowing changing the
- * parameters of an existing one) is consistent with the bandwidth
- * constraints. If yes, this function also accordingly updates the currently
- * allocated bandwidth to reflect the new situation.
- *
- * This function is called while holding p's rq->lock.
- *
- * XXX we should delay bw change until the task's 0-lag point, see
- * __setparam_dl().
- */
-static int dl_overflow(struct task_struct *p, int policy,
- const struct sched_attr *attr)
-{
-
- struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
- u64 period = attr->sched_period ?: attr->sched_deadline;
- u64 runtime = attr->sched_runtime;
- u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
- int cpus, err = -1;
-
- /* !deadline task may carry old deadline bandwidth */
- if (new_bw == p->dl.dl_bw && task_has_dl_policy(p))
- return 0;
-
- /*
- * Either if a task, enters, leave, or stays -deadline but changes
- * its parameters, we may need to update accordingly the total
- * allocated bandwidth of the container.
- */
- raw_spin_lock(&dl_b->lock);
- cpus = dl_bw_cpus(task_cpu(p));
- if (dl_policy(policy) && !task_has_dl_policy(p) &&
- !__dl_overflow(dl_b, cpus, 0, new_bw)) {
- __dl_add(dl_b, new_bw);
- err = 0;
- } else if (dl_policy(policy) && task_has_dl_policy(p) &&
- !__dl_overflow(dl_b, cpus, p->dl.dl_bw, new_bw)) {
- __dl_clear(dl_b, p->dl.dl_bw);
- __dl_add(dl_b, new_bw);
- err = 0;
- } else if (!dl_policy(policy) && task_has_dl_policy(p)) {
- __dl_clear(dl_b, p->dl.dl_bw);
- err = 0;
- }
- raw_spin_unlock(&dl_b->lock);
-
- return err;
-}
-
-extern void init_dl_bw(struct dl_bw *dl_b);
-
/*
* wake_up_new_task - wake up a newly created task for the first time.
*
@@ -3698,20 +3599,20 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
struct task_struct *pi_task = rt_mutex_get_top_task(p);
if (!dl_prio(p->normal_prio) ||
(pi_task && dl_entity_preempt(&pi_task->dl, &p->dl))) {
- p->dl.dl_boosted = 1;
+ dl_boosted(p) = 1;
queue_flag |= ENQUEUE_REPLENISH;
} else
- p->dl.dl_boosted = 0;
+ dl_boosted(p) = 0;
p->sched_class = &dl_sched_class;
} else if (rt_prio(prio)) {
if (dl_prio(oldprio))
- p->dl.dl_boosted = 0;
+ dl_boosted(p) = 0;
if (oldprio < prio)
queue_flag |= ENQUEUE_HEAD;
p->sched_class = &rt_sched_class;
} else {
if (dl_prio(oldprio))
- p->dl.dl_boosted = 0;
+ dl_boosted(p) = 0;
if (rt_prio(oldprio))
p->rt.timeout = 0;
p->sched_class = &fair_sched_class;
@@ -3895,47 +3796,6 @@ static struct task_struct *find_process_by_pid(pid_t pid)
return pid ? find_task_by_vpid(pid) : current;
}
-/*
- * This function initializes the sched_dl_entity of a newly becoming
- * SCHED_DEADLINE task.
- *
- * Only the static values are considered here, the actual runtime and the
- * absolute deadline will be properly calculated when the task is enqueued
- * for the first time with its new policy.
- */
-static void
-__setparam_dl(struct task_struct *p, const struct sched_attr *attr)
-{
- struct sched_dl_entity *dl_se = &p->dl;
-
- dl_se->dl_runtime = attr->sched_runtime;
- dl_se->dl_deadline = attr->sched_deadline;
- dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline;
- dl_se->flags = attr->sched_flags;
- dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
- dl_se->dl_density = to_ratio(dl_se->dl_deadline, dl_se->dl_runtime);
-
- /*
- * Changing the parameters of a task is 'tricky' and we're not doing
- * the correct thing -- also see task_dead_dl() and switched_from_dl().
- *
- * What we SHOULD do is delay the bandwidth release until the 0-lag
- * point. This would include retaining the task_struct until that time
- * and change dl_overflow() to not immediately decrement the current
- * amount.
- *
- * Instead we retain the current runtime/deadline and let the new
- * parameters take effect after the current reservation period lapses.
- * This is safe (albeit pessimistic) because the 0-lag point is always
- * before the current scheduling deadline.
- *
- * We can still have temporary overloads because we do not delay the
- * change in bandwidth until that time; so admission control is
- * not on the safe side. It does however guarantee tasks will never
- * consume more than promised.
- */
-}
-
/*
* sched_setparam() passes in -1 for its policy, to let the functions
* it calls know not to change it.
@@ -3990,59 +3850,6 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
p->sched_class = &fair_sched_class;
}
-static void
-__getparam_dl(struct task_struct *p, struct sched_attr *attr)
-{
- struct sched_dl_entity *dl_se = &p->dl;
-
- attr->sched_priority = p->rt_priority;
- attr->sched_runtime = dl_se->dl_runtime;
- attr->sched_deadline = dl_se->dl_deadline;
- attr->sched_period = dl_se->dl_period;
- attr->sched_flags = dl_se->flags;
-}
-
-/*
- * This function validates the new parameters of a -deadline task.
- * We ask for the deadline not being zero, and greater or equal
- * than the runtime, as well as the period of being zero or
- * greater than deadline. Furthermore, we have to be sure that
- * user parameters are above the internal resolution of 1us (we
- * check sched_runtime only since it is always the smaller one) and
- * below 2^63 ns (we have to check both sched_deadline and
- * sched_period, as the latter can be zero).
- */
-static bool
-__checkparam_dl(const struct sched_attr *attr)
-{
- /* deadline != 0 */
- if (attr->sched_deadline == 0)
- return false;
-
- /*
- * Since we truncate DL_SCALE bits, make sure we're at least
- * that big.
- */
- if (attr->sched_runtime < (1ULL << DL_SCALE))
- return false;
-
- /*
- * Since we use the MSB for wrap-around and sign issues, make
- * sure it's not set (mind that period can be equal to zero).
- */
- if (attr->sched_deadline & (1ULL << 63) ||
- attr->sched_period & (1ULL << 63))
- return false;
-
- /* runtime <= deadline <= period (if period != 0) */
- if ((attr->sched_period != 0 &&
- attr->sched_period < attr->sched_deadline) ||
- attr->sched_deadline < attr->sched_runtime)
- return false;
-
- return true;
-}
-
/*
* check the target process has a UID that matches the current process's
*/
@@ -4059,20 +3866,6 @@ static bool check_same_owner(struct task_struct *p)
return match;
}
-static bool dl_param_changed(struct task_struct *p,
- const struct sched_attr *attr)
-{
- struct sched_dl_entity *dl_se = &p->dl;
-
- if (dl_se->dl_runtime != attr->sched_runtime ||
- dl_se->dl_deadline != attr->sched_deadline ||
- dl_se->dl_period != attr->sched_period ||
- dl_se->flags != attr->sched_flags)
- return true;
-
- return false;
-}
-
static int __sched_setscheduler(struct task_struct *p,
const struct sched_attr *attr,
bool user, bool pi)
@@ -4251,7 +4044,7 @@ static int __sched_setscheduler(struct task_struct *p,
* of a SCHED_DEADLINE task) we need to check if enough bandwidth
* is available.
*/
- if ((dl_policy(policy) || dl_task(p)) && dl_overflow(p, policy, attr)) {
+ if ((dl_policy(policy) || dl_task(p)) && sched_dl_overflow(p, policy, attr)) {
task_rq_unlock(rq, p, &rf);
return -EBUSY;
}
@@ -5333,23 +5126,15 @@ void init_idle(struct task_struct *idle, int cpu)
int cpuset_cpumask_can_shrink(const struct cpumask *cur,
const struct cpumask *trial)
{
- int ret = 1, trial_cpus;
- struct dl_bw *cur_dl_b;
- unsigned long flags;
+ int ret = 1;
if (!cpumask_weight(cur))
return ret;
- rcu_read_lock_sched();
- cur_dl_b = dl_bw_of(cpumask_any(cur));
- trial_cpus = cpumask_weight(trial);
-
- raw_spin_lock_irqsave(&cur_dl_b->lock, flags);
- if (cur_dl_b->bw != -1 &&
- cur_dl_b->bw * trial_cpus < cur_dl_b->total_bw)
- ret = 0;
- raw_spin_unlock_irqrestore(&cur_dl_b->lock, flags);
- rcu_read_unlock_sched();
+#ifdef CONFIG_SMP
+ if (IS_ENABLED(CONFIG_SCHED_DL))
+ ret = dl_cpuset_cpumask_can_shrink(cur, trial);
+#endif
return ret;
}
@@ -5375,34 +5160,8 @@ int task_can_attach(struct task_struct *p,
#ifdef CONFIG_SMP
if (dl_task(p) && !cpumask_intersects(task_rq(p)->rd->span,
- cs_cpus_allowed)) {
- unsigned int dest_cpu = cpumask_any_and(cpu_active_mask,
- cs_cpus_allowed);
- struct dl_bw *dl_b;
- bool overflow;
- int cpus;
- unsigned long flags;
-
- rcu_read_lock_sched();
- dl_b = dl_bw_of(dest_cpu);
- raw_spin_lock_irqsave(&dl_b->lock, flags);
- cpus = dl_bw_cpus(dest_cpu);
- overflow = __dl_overflow(dl_b, cpus, 0, p->dl.dl_bw);
- if (overflow)
- ret = -EBUSY;
- else {
- /*
- * We reserve space for this task in the destination
- * root_domain, as we can't fail after this point.
- * We will free resources in the source root_domain
- * later on (see set_cpus_allowed_dl()).
- */
- __dl_add(dl_b, p->dl.dl_bw);
- }
- raw_spin_unlock_irqrestore(&dl_b->lock, flags);
- rcu_read_unlock_sched();
-
- }
+ cs_cpus_allowed))
+ ret = dl_task_can_attach(p, cs_cpus_allowed);
#endif
out:
return ret;
@@ -7329,23 +7088,8 @@ static void cpuset_cpu_active(void)
static int cpuset_cpu_inactive(unsigned int cpu)
{
- unsigned long flags;
- struct dl_bw *dl_b;
- bool overflow;
- int cpus;
-
if (!cpuhp_tasks_frozen) {
- rcu_read_lock_sched();
- dl_b = dl_bw_of(cpu);
-
- raw_spin_lock_irqsave(&dl_b->lock, flags);
- cpus = dl_bw_cpus(cpu);
- overflow = __dl_overflow(dl_b, cpus, 0, 0);
- raw_spin_unlock_irqrestore(&dl_b->lock, flags);
-
- rcu_read_unlock_sched();
-
- if (overflow)
+ if (dl_cpu_busy(cpu))
return -EBUSY;
cpuset_update_active_cpus(false);
} else {
@@ -8235,70 +7979,6 @@ static int sched_rt_global_constraints(void)
}
#endif /* CONFIG_RT_GROUP_SCHED */
-static int sched_dl_global_validate(void)
-{
- u64 runtime = global_rt_runtime();
- u64 period = global_rt_period();
- u64 new_bw = to_ratio(period, runtime);
- struct dl_bw *dl_b;
- int cpu, ret = 0;
- unsigned long flags;
-
- /*
- * Here we want to check the bandwidth not being set to some
- * value smaller than the currently allocated bandwidth in
- * any of the root_domains.
- *
- * FIXME: Cycling on all the CPUs is overdoing, but simpler than
- * cycling on root_domains... Discussion on different/better
- * solutions is welcome!
- */
- for_each_possible_cpu(cpu) {
- rcu_read_lock_sched();
- dl_b = dl_bw_of(cpu);
-
- raw_spin_lock_irqsave(&dl_b->lock, flags);
- if (new_bw < dl_b->total_bw)
- ret = -EBUSY;
- raw_spin_unlock_irqrestore(&dl_b->lock, flags);
-
- rcu_read_unlock_sched();
-
- if (ret)
- break;
- }
-
- return ret;
-}
-
-static void sched_dl_do_global(void)
-{
- u64 new_bw = -1;
- struct dl_bw *dl_b;
- int cpu;
- unsigned long flags;
-
- def_dl_bandwidth.dl_period = global_rt_period();
- def_dl_bandwidth.dl_runtime = global_rt_runtime();
-
- if (global_rt_runtime() != RUNTIME_INF)
- new_bw = to_ratio(global_rt_period(), global_rt_runtime());
-
- /*
- * FIXME: As above...
- */
- for_each_possible_cpu(cpu) {
- rcu_read_lock_sched();
- dl_b = dl_bw_of(cpu);
-
- raw_spin_lock_irqsave(&dl_b->lock, flags);
- dl_b->bw = new_bw;
- raw_spin_unlock_irqrestore(&dl_b->lock, flags);
-
- rcu_read_unlock_sched();
- }
-}
-
static int sched_rt_global_validate(void)
{
if (sysctl_sched_rt_period <= 0)
@@ -8336,16 +8016,19 @@ int sched_rt_handler(struct ctl_table *table, int write,
if (ret)
goto undo;
- ret = sched_dl_global_validate();
- if (ret)
- goto undo;
+ if (IS_ENABLED(CONFIG_SCHED_DL)) {
+ ret = sched_dl_global_validate();
+ if (ret)
+ goto undo;
+ }
ret = sched_rt_global_constraints();
if (ret)
goto undo;
sched_rt_do_global();
- sched_dl_do_global();
+ if (IS_ENABLED(CONFIG_SCHED_DL))
+ sched_dl_do_global();
}
if (0) {
undo:
diff --git a/kernel/sched/cpudeadline.h b/kernel/sched/cpudeadline.h
index f7da8c55..5f4c10f8 100644
--- a/kernel/sched/cpudeadline.h
+++ b/kernel/sched/cpudeadline.h
@@ -25,10 +25,15 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
struct cpumask *later_mask);
void cpudl_set(struct cpudl *cp, int cpu, u64 dl);
void cpudl_clear(struct cpudl *cp, int cpu);
-int cpudl_init(struct cpudl *cp);
void cpudl_set_freecpu(struct cpudl *cp, int cpu);
void cpudl_clear_freecpu(struct cpudl *cp, int cpu);
+#ifdef CONFIG_SCHED_DL
+int cpudl_init(struct cpudl *cp);
void cpudl_cleanup(struct cpudl *cp);
+#else
+#define cpudl_init(cp) 0
+#define cpudl_cleanup(cp) do { } while (0)
+#endif
#endif /* CONFIG_SMP */
#endif /* _LINUX_CPUDL_H */
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 3042927c..dc18a4c7 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -43,6 +43,38 @@ static inline int on_dl_rq(struct sched_dl_entity *dl_se)
return !RB_EMPTY_NODE(&dl_se->rb_node);
}
+#ifdef CONFIG_SMP
+static inline struct dl_bw *dl_bw_of(int i)
+{
+ RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
+ "sched RCU must be held");
+ return &cpu_rq(i)->rd->dl_bw;
+}
+
+static inline int dl_bw_cpus(int i)
+{
+ struct root_domain *rd = cpu_rq(i)->rd;
+ int cpus = 0;
+
+ RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
+ "sched RCU must be held");
+ for_each_cpu_and(i, rd->span, cpu_active_mask)
+ cpus++;
+
+ return cpus;
+}
+#else
+static inline struct dl_bw *dl_bw_of(int i)
+{
+ return &cpu_rq(i)->dl.dl_bw;
+}
+
+static inline int dl_bw_cpus(int i)
+{
+ return 1;
+}
+#endif
+
static inline int is_leftmost(struct task_struct *p, struct dl_rq *dl_rq)
{
struct sched_dl_entity *dl_se = &p->dl;
@@ -1931,6 +1963,300 @@ const struct sched_class dl_sched_class = {
.update_curr = update_curr_dl,
};
+int sched_dl_global_validate(void)
+{
+ u64 runtime = global_rt_runtime();
+ u64 period = global_rt_period();
+ u64 new_bw = to_ratio(period, runtime);
+ struct dl_bw *dl_b;
+ int cpu, ret = 0;
+ unsigned long flags;
+
+ /*
+ * Here we want to check the bandwidth not being set to some
+ * value smaller than the currently allocated bandwidth in
+ * any of the root_domains.
+ *
+ * FIXME: Cycling on all the CPUs is overdoing, but simpler than
+ * cycling on root_domains... Discussion on different/better
+ * solutions is welcome!
+ */
+ for_each_possible_cpu(cpu) {
+ rcu_read_lock_sched();
+ dl_b = dl_bw_of(cpu);
+ raw_spin_lock_irqsave(&dl_b->lock, flags);
+ if (new_bw < dl_b->total_bw)
+ ret = -EBUSY;
+ raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+
+ rcu_read_unlock_sched();
+
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+void sched_dl_do_global(void)
+{
+ u64 new_bw = -1;
+ struct dl_bw *dl_b;
+ int cpu;
+ unsigned long flags;
+
+ def_dl_bandwidth.dl_period = global_rt_period();
+ def_dl_bandwidth.dl_runtime = global_rt_runtime();
+
+ if (global_rt_runtime() != RUNTIME_INF)
+ new_bw = to_ratio(global_rt_period(), global_rt_runtime());
+
+ /*
+ * FIXME: As above...
+ */
+ for_each_possible_cpu(cpu) {
+ rcu_read_lock_sched();
+ dl_b = dl_bw_of(cpu);
+
+ raw_spin_lock_irqsave(&dl_b->lock, flags);
+ dl_b->bw = new_bw;
+ raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+
+ rcu_read_unlock_sched();
+ }
+}
+
+/*
+ * We must be sure that accepting a new task (or allowing changing the
+ * parameters of an existing one) is consistent with the bandwidth
+ * constraints. If yes, this function also accordingly updates the currently
+ * allocated bandwidth to reflect the new situation.
+ *
+ * This function is called while holding p's rq->lock.
+ */
+int sched_dl_overflow(struct task_struct *p, int policy,
+ const struct sched_attr *attr)
+{
+ struct dl_bw *dl_b = dl_bw_of(task_cpu(p));
+ u64 period = attr->sched_period ?: attr->sched_deadline;
+ u64 runtime = attr->sched_runtime;
+ u64 new_bw = dl_policy(policy) ? to_ratio(period, runtime) : 0;
+ int cpus, err = -1;
+
+ /* !deadline task may carry old deadline bandwidth */
+ if (new_bw == p->dl.dl_bw && task_has_dl_policy(p))
+ return 0;
+
+ /*
+ * Either if a task, enters, leave, or stays -deadline but changes
+ * its parameters, we may need to update accordingly the total
+ * allocated bandwidth of the container.
+ */
+ raw_spin_lock(&dl_b->lock);
+ cpus = dl_bw_cpus(task_cpu(p));
+ if (dl_policy(policy) && !task_has_dl_policy(p) &&
+ !__dl_overflow(dl_b, cpus, 0, new_bw)) {
+ __dl_add(dl_b, new_bw);
+ err = 0;
+ } else if (dl_policy(policy) && task_has_dl_policy(p) &&
+ !__dl_overflow(dl_b, cpus, p->dl.dl_bw, new_bw)) {
+ /*
+ * XXX this is slightly incorrect: when the task
+ * utilization decreases, we should delay the total
+ * utilization change until the task's 0-lag point.
+ * But this would require to set the task's "inactive
+ * timer" when the task is not inactive.
+ */
+ __dl_clear(dl_b, p->dl.dl_bw);
+ __dl_add(dl_b, new_bw);
+ err = 0;
+ } else if (!dl_policy(policy) && task_has_dl_policy(p)) {
+ /*
+ * Do not decrease the total deadline utilization here,
+ * switched_from_dl() will take care to do it at the correct
+ * (0-lag) time.
+ */
+ __dl_clear(dl_b, p->dl.dl_bw);
+ err = 0;
+ }
+ raw_spin_unlock(&dl_b->lock);
+
+ return err;
+}
+
+/*
+ * This function initializes the sched_dl_entity of a newly becoming
+ * SCHED_DEADLINE task.
+ *
+ * Only the static values are considered here, the actual runtime and the
+ * absolute deadline will be properly calculated when the task is enqueued
+ * for the first time with its new policy.
+ */
+void __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
+{
+ struct sched_dl_entity *dl_se = &p->dl;
+
+ dl_se->dl_runtime = attr->sched_runtime;
+ dl_se->dl_deadline = attr->sched_deadline;
+ dl_se->dl_period = attr->sched_period ?: dl_se->dl_deadline;
+ dl_se->flags = attr->sched_flags;
+ dl_se->dl_bw = to_ratio(dl_se->dl_period, dl_se->dl_runtime);
+ dl_se->dl_density = to_ratio(dl_se->dl_deadline, dl_se->dl_runtime);
+}
+
+void __getparam_dl(struct task_struct *p, struct sched_attr *attr)
+{
+ struct sched_dl_entity *dl_se = &p->dl;
+
+ attr->sched_priority = p->rt_priority;
+ attr->sched_runtime = dl_se->dl_runtime;
+ attr->sched_deadline = dl_se->dl_deadline;
+ attr->sched_period = dl_se->dl_period;
+ attr->sched_flags = dl_se->flags;
+}
+
+/*
+ * This function validates the new parameters of a -deadline task.
+ * We ask for the deadline not being zero, and greater or equal
+ * than the runtime, as well as the period of being zero or
+ * greater than deadline. Furthermore, we have to be sure that
+ * user parameters are above the internal resolution of 1us (we
+ * check sched_runtime only since it is always the smaller one) and
+ * below 2^63 ns (we have to check both sched_deadline and
+ * sched_period, as the latter can be zero).
+ */
+bool __checkparam_dl(const struct sched_attr *attr)
+{
+ /* deadline != 0 */
+ if (attr->sched_deadline == 0)
+ return false;
+
+ /*
+ * Since we truncate DL_SCALE bits, make sure we're at least
+ * that big.
+ */
+ if (attr->sched_runtime < (1ULL << DL_SCALE))
+ return false;
+
+ /*
+ * Since we use the MSB for wrap-around and sign issues, make
+ * sure it's not set (mind that period can be equal to zero).
+ */
+ if (attr->sched_deadline & (1ULL << 63) ||
+ attr->sched_period & (1ULL << 63))
+ return false;
+
+ /* runtime <= deadline <= period (if period != 0) */
+ if ((attr->sched_period != 0 &&
+ attr->sched_period < attr->sched_deadline) ||
+ attr->sched_deadline < attr->sched_runtime)
+ return false;
+
+ return true;
+}
+
+/*
+ * This function clears the sched_dl_entity static params.
+ */
+void __dl_clear_params(struct task_struct *p)
+{
+ struct sched_dl_entity *dl_se = &p->dl;
+
+ dl_se->dl_runtime = 0;
+ dl_se->dl_deadline = 0;
+ dl_se->dl_period = 0;
+ dl_se->flags = 0;
+ dl_se->dl_bw = 0;
+ dl_se->dl_density = 0;
+
+ dl_se->dl_throttled = 0;
+ dl_se->dl_yielded = 0;
+}
+
+bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr)
+{
+ struct sched_dl_entity *dl_se = &p->dl;
+
+ if (dl_se->dl_runtime != attr->sched_runtime ||
+ dl_se->dl_deadline != attr->sched_deadline ||
+ dl_se->dl_period != attr->sched_period ||
+ dl_se->flags != attr->sched_flags)
+ return true;
+
+ return false;
+}
+
+#ifdef CONFIG_SMP
+int dl_task_can_attach(struct task_struct *p,
+ const struct cpumask *cs_cpus_allowed)
+{
+ unsigned int dest_cpu = cpumask_any_and(cpu_active_mask,
+ cs_cpus_allowed);
+ struct dl_bw *dl_b;
+ bool overflow;
+ int cpus, ret;
+ unsigned long flags;
+
+ rcu_read_lock_sched();
+ dl_b = dl_bw_of(dest_cpu);
+ raw_spin_lock_irqsave(&dl_b->lock, flags);
+ cpus = dl_bw_cpus(dest_cpu);
+ overflow = __dl_overflow(dl_b, cpus, 0, p->dl.dl_bw);
+ if (overflow)
+ ret = -EBUSY;
+ else {
+ /*
+ * We reserve space for this task in the destination
+ * root_domain, as we can't fail after this point.
+ * We will free resources in the source root_domain
+ * later on (see set_cpus_allowed_dl()).
+ */
+ __dl_add(dl_b, p->dl.dl_bw);
+ ret = 0;
+ }
+ raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+ rcu_read_unlock_sched();
+ return ret;
+}
+
+int dl_cpuset_cpumask_can_shrink(const struct cpumask *cur,
+ const struct cpumask *trial)
+{
+ int ret = 1, trial_cpus;
+ struct dl_bw *cur_dl_b;
+ unsigned long flags;
+
+ rcu_read_lock_sched();
+ cur_dl_b = dl_bw_of(cpumask_any(cur));
+ trial_cpus = cpumask_weight(trial);
+
+ raw_spin_lock_irqsave(&cur_dl_b->lock, flags);
+ if (cur_dl_b->bw != -1 &&
+ cur_dl_b->bw * trial_cpus < cur_dl_b->total_bw)
+ ret = 0;
+ raw_spin_unlock_irqrestore(&cur_dl_b->lock, flags);
+ rcu_read_unlock_sched();
+ return ret;
+}
+
+bool dl_cpu_busy(unsigned int cpu)
+{
+ unsigned long flags;
+ struct dl_bw *dl_b;
+ bool overflow;
+ int cpus;
+
+ rcu_read_lock_sched();
+ dl_b = dl_bw_of(cpu);
+ raw_spin_lock_irqsave(&dl_b->lock, flags);
+ cpus = dl_bw_cpus(cpu);
+ overflow = __dl_overflow(dl_b, cpus, 0, 0);
+ raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+ rcu_read_unlock_sched();
+ return overflow;
+}
+#endif
+
#ifdef CONFIG_SCHED_DEBUG
extern void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq);
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index fa178b62..1b8b6936 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -645,7 +645,9 @@ do { \
spin_lock_irqsave(&sched_debug_lock, flags);
print_cfs_stats(m, cpu);
print_rt_stats(m, cpu);
+#ifdef CONFIG_SCHED_DL
print_dl_stats(m, cpu);
+#endif
print_rq(m, rq, cpu);
spin_unlock_irqrestore(&sched_debug_lock, flags);
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 9ab4d73e..8005cb00 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1535,7 +1535,7 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev, struct pin_cookie coo
* to re-start task selection.
*/
if (unlikely((rq->stop && task_on_rq_queued(rq->stop)) ||
- rq->dl.dl_nr_running))
+ dl_nr_running(rq)))
return RETRY_TASK;
}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index f564a1d2..86582ccc 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -121,7 +121,7 @@ static inline int rt_policy(int policy)
static inline int dl_policy(int policy)
{
- return policy == SCHED_DEADLINE;
+ return IS_ENABLED(CONFIG_SCHED_DL) && policy == SCHED_DEADLINE;
}
static inline bool valid_policy(int policy)
{
@@ -142,12 +142,15 @@ static inline int task_has_dl_policy(struct task_struct *p)
/*
* Tells if entity @a should preempt entity @b.
*/
+#ifdef CONFIG_SCHED_DL
static inline bool
dl_entity_preempt(struct sched_dl_entity *a, struct sched_dl_entity *b)
{
return dl_time_before(a->deadline, b->deadline);
}
-
+#else
+#define dl_entity_preempt(a, b) false
+#endif
/*
* This is the priority-queue data structure of the RT scheduling class:
*/
@@ -202,8 +205,6 @@ static inline int dl_bandwidth_enabled(void)
return sysctl_sched_rt_runtime >= 0;
}
-extern struct dl_bw *dl_bw_of(int i);
-
struct dl_bw {
raw_spinlock_t lock;
u64 bw, total_bw;
@@ -636,7 +637,9 @@ struct rq {
struct cfs_rq cfs;
struct rt_rq rt;
+#ifdef CONFIG_SCHED_DL
struct dl_rq dl;
+#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
/* list of leaf cfs_rq on this cpu: */
@@ -1291,7 +1294,13 @@ static inline void set_curr_task(struct rq *rq, struct task_struct *curr)
curr->sched_class->set_curr_task(rq);
}
+#ifdef CONFIG_SMP
#define sched_class_highest (&stop_sched_class)
+#elif defined(CONFIG_SCHED_DL)
+#define sched_class_highest (&dl_sched_class)
+#else
+#define sched_class_highest (&rt_sched_class)
+#endif
#define for_each_class(class) \
for (class = sched_class_highest; class; class = class->next)
@@ -1340,7 +1349,6 @@ extern void sysrq_sched_debug_show(void);
extern void sched_init_granularity(void);
extern void update_max_interval(void);
-extern void init_sched_dl_class(void);
extern void init_sched_rt_class(void);
extern void init_sched_fair_class(void);
@@ -1350,8 +1358,6 @@ extern void resched_cpu(int cpu);
extern struct rt_bandwidth def_rt_bandwidth;
extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime);
-extern struct dl_bandwidth def_dl_bandwidth;
-extern void init_dl_bandwidth(struct dl_bandwidth *dl_b, u64 period, u64 runtime);
extern void init_dl_task_timer(struct sched_dl_entity *dl_se);
unsigned long to_ratio(u64 period, u64 runtime);
@@ -1722,7 +1728,6 @@ print_numa_stats(struct seq_file *m, int node, unsigned long tsf,
extern void init_cfs_rq(struct cfs_rq *cfs_rq);
extern void init_rt_rq(struct rt_rq *rt_rq);
-extern void init_dl_rq(struct dl_rq *dl_rq);
extern void cfs_bandwidth_usage_inc(void);
extern void cfs_bandwidth_usage_dec(void);
diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c
index 604297a0..88c295f7 100644
--- a/kernel/sched/stop_task.c
+++ b/kernel/sched/stop_task.c
@@ -110,7 +110,11 @@ static void update_curr_stop(struct rq *rq)
* Simple, special scheduling class for the per-CPU stop tasks:
*/
const struct sched_class stop_sched_class = {
+#ifdef CONFIG_SCHED_DL
.next = &dl_sched_class,
+#else
+ .next = &rt_sched_class,
+#endif
.enqueue_task = enqueue_task_stop,
.dequeue_task = dequeue_task_stop,
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 635482e6..9667ee57 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -160,6 +160,10 @@ cond_syscall(sys_uselib);
cond_syscall(sys_fadvise64);
cond_syscall(sys_fadvise64_64);
cond_syscall(sys_madvise);
+cond_syscall(sys_adjtimex);
+cond_syscall(compat_sys_adjtimex);
+cond_syscall(sys_clock_adjtime);
+cond_syscall(compat_sys_clock_adjtime);
cond_syscall(sys_setuid);
cond_syscall(sys_setregid);
cond_syscall(sys_setgid);
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 49eca0be..b8931024 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,5 +1,5 @@
obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o
-obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
+obj-y += timekeeping.o clocksource.o jiffies.o timer_list.o
obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o tick-common.o
@@ -12,3 +12,4 @@ obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o
obj-$(CONFIG_TIMER_STATS) += timer_stats.o
obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
+obj-$(CONFIG_NTP) += ntp.o
diff --git a/kernel/time/ntp_internal.h b/kernel/time/ntp_internal.h
index d8a7c11f..ff7efb74 100644
--- a/kernel/time/ntp_internal.h
+++ b/kernel/time/ntp_internal.h
@@ -1,6 +1,6 @@
#ifndef _LINUX_NTP_INTERNAL_H
#define _LINUX_NTP_INTERNAL_H
-
+#ifdef CONFIG_NTP
extern void ntp_init(void);
extern void ntp_clear(void);
/* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */
@@ -10,4 +10,38 @@ extern int second_overflow(time64_t secs);
extern int ntp_validate_timex(struct timex *);
extern int __do_adjtimex(struct timex *, struct timespec64 *, s32 *);
extern void __hardpps(const struct timespec64 *, const struct timespec64 *);
+#else
+static inline void ntp_init(void)
+{}
+static inline void ntp_clear(void)
+{}
+static inline u64 ntp_tick_length(void)
+{
+ //10000000<<32 (NSEC_PER_SEC<<NTP_SCALED_SHIFT)
+ return 42949672960000000ULL;
+}
+static inline int second_overflow(unsigned long secs)
+{
+ return 0;
+}
+static inline int ntp_validate_timex(struct timex *txc)
+{
+ return 0;
+}
+static inline int __do_adjtimex(struct timex *txc, struct timespec64 *ts,
+ s32 *time_tai)
+{
+ return 0;
+}
+static inline void __hardpps(const struct timespec *ts1,
+ const struct timespec *ts2)
+{}
+static inline ktime_t ntp_get_next_leap(void)
+{
+ ktime_t ret;
+
+ ret.tv64 = KTIME_MAX;
+ return ret;
+}
+#endif
#endif /* _LINUX_NTP_INTERNAL_H */
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index fc7c37ad..20dc5e48 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1045,7 +1045,7 @@ SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
return error;
}
-
+#ifdef CONFIG_NTP
SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
struct timex __user *, utx)
{
@@ -1068,7 +1068,7 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
return err;
}
-
+#endif
SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
struct timespec __user *, tp)
{
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 39468651..1911e8c9 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -215,7 +215,7 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
}
-
+#ifdef CONFIG_NTP
SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
{
struct timex txc; /* Local copy of parameter */
@@ -230,7 +230,7 @@ SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
ret = do_adjtimex(&txc);
return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
}
-
+#endif
/**
* current_fs_time - Return FS time
* @sb: Superblock.
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d831827d..15711414 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2268,7 +2268,7 @@ ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq, ktime_t *offs_real,
return base;
}
-
+#ifdef CONFIG_NTP
/**
* do_adjtimex() - Accessor function to NTP __do_adjtimex function
*/
@@ -2320,7 +2320,7 @@ int do_adjtimex(struct timex *txc)
return ret;
}
-
+#endif
#ifdef CONFIG_NTP_PPS
/**
* hardpps() - Accessor function to NTP __hardpps function
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index b625cc7f..f152b1c9 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -160,7 +160,11 @@ EXPORT_SYMBOL(jiffies_64);
#define LVL_START(n) ((LVL_SIZE - 1) << (((n) - 1) * LVL_CLK_SHIFT))
/* Size of each clock level */
+#ifdef CONFIG_TINY_KERNEL
+#define LVL_BITS 4
+#else
#define LVL_BITS 6
+#endif
#define LVL_SIZE (1UL << LVL_BITS)
#define LVL_MASK (LVL_SIZE - 1)
#define LVL_OFFS(n) ((n) * LVL_SIZE)
diff --git a/ksyms_whitelists/fh8852v200_whitelist b/ksyms_whitelists/fh8852v200_whitelist
new file mode 100644
index 00000000..03e794e3
--- /dev/null
+++ b/ksyms_whitelists/fh8852v200_whitelist
@@ -0,0 +1,663 @@
+__aeabi_idiv
+__aeabi_idivmod
+__aeabi_uidiv
+__aeabi_uidivmod
+__aeabi_unwind_cpp_pr1
+__class_create
+__init_waitqueue_head
+__kmalloc
+__msecs_to_jiffies
+__mutex_init
+__pv_phys_pfn_offset
+__wake_up
+alloc_chrdev_region
+anon_inode_getfd
+arm_copy_from_user
+arm_copy_to_user
+arm_delay_ops
+arm_dma_ops
+autoremove_wake_function
+cacheid
+cdev_add
+cdev_del
+cdev_init
+class_destroy
+clk_disable
+clk_enable
+clk_get
+clk_put
+clk_prepare
+clk_unprepare
+complete
+del_timer
+device_create
+device_destroy
+dma_alloc_from_coherent
+dma_release_from_coherent
+do_gettimeofday
+down
+fh_aes_128_ecb_encrypt
+fh_setscheduler
+fh_clk_enable
+fh_clk_get_rate
+fh_clk_set_rate
+fh_clk_prepare
+fh_clk_disable
+fh_clk_unprepare
+fh_clk_prepare_enable
+fh_clk_disable_unprepare
+fh_clk_set_parent
+fh_clk_get_parent
+fh_clk_has_parent
+fh_get_chipid
+fh_get_chipname
+fh_get_ddrsize_mbit
+fh_irq_create_mapping
+fh_mb_resize_maxdata
+fh_pmu_get_reg
+fh_pmu_set_reg
+fh_pmu_set_reg_m
+fh_setscheduler
+finish_wait
+free_irq
+get_chip_info
+high_memory
+init_timer_key
+init_wait_entry
+ioremap
+iounmap
+irq_create_mapping
+jiffies
+kfree
+kmalloc_caches
+kmalloc_order
+kmem_cache_alloc
+kmem_cache_create
+kmem_cache_destroy
+kmem_cache_free
+kthread_create_on_node
+kthread_should_stop
+kthread_stop
+memcpy
+memset
+misc_deregister
+misc_register
+mod_timer
+msleep
+mutex_lock
+mutex_lock_interruptible
+mutex_trylock
+mutex_unlock
+noop_llseek
+param_ops_int
+param_ops_string
+param_ops_uint
+pool_get_free_ex
+pool_get_use_size
+pool_put_free
+pool_put_use
+preempt_count_add
+preempt_count_sub
+preempt_schedule
+prepare_to_wait
+prepare_to_wait_event
+printk
+proc_create_data
+release_firmware
+remap_pfn_range
+remove_proc_entry
+request_firmware
+request_threaded_irq
+sched_setscheduler
+schedule
+schedule_timeout
+seq_open
+seq_printf
+seq_read
+seq_release
+simple_strtol
+simple_strtoul
+snprintf
+sprintf
+strcmp
+strcpy
+strlcpy
+strlen
+strncasecmp
+strncmp
+strncpy
+strnlen_user
+strsep
+unregister_chrdev_region
+up
+v6_flush_kern_cache_all
+v6_flush_kern_dcache_area
+vfree
+vm_mmap
+vmalloc
+vsnprintf
+wait_for_completion
+wait_for_completion_interruptible
+wake_up_process
+warn_slowpath_null
+fh_confidence_map_gen
+fh_drop_decide
+fh_drop_update
+fh_generate_smart_cfg_table
+fh_rc_Init
+fh_rc_change_param
+fh_rc_get_qp
+fh_rc_update
+fh_register_h264_callback
+fh_unregister_h264_callback
+fhk_mtrace
+fhk_trace
+generaterandseed
+get_pts
+get_pts64
+get_pts_rate
+get_ptsh_from_pts64
+get_ptsl_from_pts64
+jpeg_queue_get
+jpeg_queue_num
+jpeg_queue_put
+jpeg_queue_query
+meantime2fps
+meantime2fps_string
+media_close_low_power
+media_disable_clk
+media_disable_clk_flag_safe
+media_disable_clk_safe
+media_enable_clk_flag_safe
+media_enable_clk_safe
+media_encode_lock
+media_encode_unlock
+media_frmrate_status
+media_generatekey
+media_getbind
+media_info_find
+media_info_register
+media_info_unregister
+media_init_low_power
+media_is_low_power_mode
+media_malloc
+media_new_frame_wakeup
+media_object_register
+media_object_unregister
+media_query_encoder_need_stmsize
+media_query_malloc_stmsize
+media_stream_buff_malloc
+media_stream_buff_unmap
+media_stream_calc_addr
+media_stream_chn_size
+media_stream_get_info
+media_stream_mem_get_free
+media_stream_pool_to_queue
+media_stream_query
+media_stream_register
+media_stream_release
+media_stream_unregister
+media_uninit_low_power
+tms_end
+tms_get_avg
+tms_get_max
+tms_get_winsize
+tms_init
+tms_start
+vbus_mesg_deinit
+vbus_mesg_init
+vbus_mesg_initcallback
+vbus_mesg_write
+yuv_check_mem_range
+yuv_queue_get
+yuv_queue_num
+yuv_queue_put
+yuv_queue_query
+/* RTL8192FS */
+eth_type_trans
+single_release
+sdio_writew
+register_netdevice_notifier
+cfg80211_mgmt_tx_status
+sdio_writel
+proc_mkdir_data
+dev_get_by_name
+sdio_writeb
+wiphy_apply_custom_regulatory
+ieee80211_frequency_to_channel
+sdio_memcpy_fromio
+cfg80211_rx_mgmt
+kern_path
+free_netdev
+__cfg80211_alloc_reply_skb
+__csum_ipv6_magic
+unregister_netdevice_queue
+system_wq
+__pskb_copy_fclone
+sdio_release_host
+yield
+ktime_get_with_offset
+register_inet6addr_notifier
+sdio_release_irq
+print_hex_dump
+alloc_etherdev_mqs
+cfg80211_new_sta
+sdio_set_host_pm_flags
+unregister_netdev
+sdio_get_host_pm_caps
+flush_signals
+unregister_netdevice_notifier
+cfg80211_inform_bss_frame_data
+dev_alloc_name
+__local_bh_enable_ip
+netif_carrier_on
+cfg80211_unlink_bss
+__dev_kfree_skb_any
+find_vpid
+sdio_set_block_size
+skb_push
+wait_for_completion_timeout
+__usecs_to_jiffies
+dev_err
+kernel_sigaction
+single_open_size
+kill_pid
+skb_trim
+unregister_inetaddr_notifier
+_test_and_clear_bit
+sdio_enable_func
+register_netdev
+sdio_memcpy_toio
+sdio_writesb
+cfg80211_put_bss
+cfg80211_roamed
+register_inetaddr_notifier
+cfg80211_scan_done
+sdio_claim_irq
+sdio_readb
+sdio_register_driver
+netif_carrier_off
+ns_to_timespec
+__vfs_read
+_set_bit
+_clear_bit
+register_netdevice
+seq_lseek
+PDE_DATA
+skb_copy
+param_ops_charp
+skb_copy_bits
+cfg80211_ibss_joined
+netif_rx
+tasklet_kill
+skb_dequeue
+cfg80211_michael_mic_failure
+netif_tx_wake_queue
+complete_and_exit
+cfg80211_disconnected
+prandom_u32
+strpbrk
+init_net
+__cfg80211_send_event_skb
+strchr
+sdio_claim_host
+sdio_readw
+cfg80211_get_bss
+wiphy_new_nm
+param_array_ops
+wiphy_free
+queue_work_on
+sdio_readl
+sdio_unregister_driver
+down_interruptible
+proc_get_parent_data
+__vfs_write
+sdio_readsb
+sdio_disable_func
+skb_put
+__ieee80211_get_channel
+csum_partial
+cfg80211_ready_on_channel
+usleep_range
+__do_div64
+skb_clone
+filp_close
+memmove
+cfg80211_ch_switch_notify
+netif_wake_subqueue
+single_open
+__pskb_pull_tail
+cfg80211_connect_bss
+jiffies_to_msecs
+filp_open
+wiphy_unregister
+netif_tx_stop_all_queues
+cfg80211_del_sta_sinfo
+tasklet_init
+sdio_f0_writeb
+cfg80211_vendor_cmd_reply
+__tasklet_schedule
+sscanf
+sdio_f0_readb
+__netdev_alloc_skb
+nla_put_nohdr
+cfg80211_remain_on_channel_expired
+nla_put
+wiphy_register
+__cfg80211_alloc_event_skb
+memcmp
+unregister_inet6addr_notifier
+rtnl_is_locked
+skb_pull
+/* Cypress 43438/43455 */
+disable_irq
+disable_irq_nosync
+irq_set_irq_wake
+enable_irq
+_change_bit
+fh_pinctrl_sdev
+sg_init_table
+__kfifo_out
+generic_file_llseek
+mem_map
+strspn
+get_random_bytes
+remove_wait_queue
+rtnl_lock
+gpio_request
+cfg80211_chandef_create
+gpio_to_desc
+delayed_work_timer_fn
+cancel_work_sync
+platform_bus_type
+kmemdup
+ieee80211_channel_to_frequency
+cancel_delayed_work_sync
+rfkill_register
+cfg80211_unregister_wdev
+skb_realloc_headroom
+__platform_driver_register
+__kfifo_init
+default_wake_function
+mmc_wait_for_req
+kernel_read
+netif_rx_ni
+rfkill_alloc
+netlink_kernel_release
+strcasecmp
+mmc_set_data_timeout
+register_pm_notifier
+dev_close
+strstr
+synchronize_sched
+netlink_unicast
+add_timer
+gpiod_direction_output_raw
+bus_find_device
+device_init_wakeup
+sort
+strcat
+unregister_reboot_notifier
+capable
+strrchr
+__alloc_skb
+fh_sdio_card_scan
+register_reboot_notifier
+queue_delayed_work_on
+sched_clock
+jiffies_to_usecs
+__kfifo_free
+platform_get_resource_byname
+cfg80211_find_ie_match
+gpio_free
+__netlink_kernel_create
+add_wait_queue
+pm_stay_awake
+rfkill_destroy
+unregister_pm_notifier
+pm_relax
+__kfifo_in
+consume_skb
+platform_driver_unregister
+rfkill_unregister
+__nlmsg_put
+down_timeout
+rtnl_unlock
+/* sdio Marvell 8801 */
+iw_handler_set_thrspy
+__alloc_workqueue_key
+cfg80211_inform_bss_data
+cfg80211_report_wowlan_wakeup
+cfg80211_pmksa_candidate_notify
+proc_mkdir
+_ctype
+iw_handler_get_spy
+panic
+wireless_send_event
+vprintk
+destroy_workqueue
+request_firmware_nowait
+up_write
+flush_workqueue
+ieee80211_bss_get_ie
+module_put
+netif_device_attach
+netif_device_detach
+hex_dump_to_buffer
+netlink_broadcast
+iw_handler_get_thrspy
+in4_pton
+dump_stack
+vfs_mkdir
+kern_path_create
+eth_validate_addr
+iw_handler_set_spy
+regulatory_hint
+cfg80211_sched_scan_stopped
+dev_set_name
+strim
+try_module_get
+device_set_wakeup_enable
+vfs_write
+cfg80211_sched_scan_results
+/* Realtek 8189ftv */
+__napi_schedule
+napi_gro_receive
+skb_queue_tail
+napi_disable
+netif_receive_skb
+netif_napi_add
+napi_complete_done
+netif_napi_del
+/* usb Marvell 8801 */
+usb_init_urb
+system_freezing_cnt
+usb_kill_urb
+usb_enable_autosuspend
+usb_disable_autosuspend
+freezing_slow_path
+strncat
+usb_deregister
+usb_submit_urb
+usb_get_dev
+usb_reset_device
+usb_bulk_msg
+usb_put_dev
+__refrigerator
+usb_register_driver
+pm_runtime_set_autosuspend_delay
+usb_free_urb
+usb_alloc_urb
+/* RTL8188FTV */
+usb_alloc_coherent
+__tasklet_hi_schedule
+usb_control_msg
+usb_autopm_get_interface
+usb_free_coherent
+init_dummy_netdev
+cfg80211_sched_scan_stopped_rtnl
+nla_parse
+getrawmonotonic64
+param_ops_ushort
+usb_autopm_put_interface
+/* ATBM6032 */
+synchronize_net
+_find_first_bit_le
+cfg80211_rx_unprot_mlme_mgmt
+cfg80211_auth_timeout
+kobject_put
+flush_work
+__request_module
+cfg80211_cqm_rssi_notify
+pm_qos_request
+usb_wait_anchor_empty_timeout
+round_jiffies
+bridge_tunnel_header
+schedule_timeout_uninterruptible
+skb_pad
+_find_first_zero_bit_le
+dev_printk
+ieee80211_hdrlen
+__aeabi_llsl
+ieee80211_radiotap_iterator_next
+usb_unlink_urb
+sysfs_remove_group
+kobject_create_and_add
+usb_unanchor_urb
+usb_block_urb
+__hw_addr_sync
+vfs_read
+rfc1042_header
+skb_queue_purge
+kernel_param_unlock
+cancel_delayed_work
+unregister_netdevice_many
+usb_lock_device_for_reset
+down_trylock
+print_hex_dump_bytes
+sysfs_create_group
+ieee80211_data_to_8023_exthdr
+ieee80211_radiotap_iterator_init
+nla_find
+platform_device_alloc
+pm_qos_add_notifier
+usb_unpoison_urb
+platform_device_add
+crc32_le
+cfg80211_cqm_pktloss_notify
+__dev_kfree_skb_irq
+platform_device_unregister
+cfg80211_report_obss_beacon
+memchr
+cfg80211_rx_spurious_frame
+kernel_param_lock
+cfg80211_assoc_timeout
+__sw_hweight64
+skb_copy_expand
+cfg80211_gtk_rekey_notify
+_dev_info
+cfg80211_tx_mlme_mgmt
+cfg80211_rx_mlme_mgmt
+cfg80211_classify8021d
+kfree_skb
+flush_delayed_work
+alloc_netdev_mqs
+atomic64_add_return
+crypto_destroy_tfm
+round_jiffies_up
+pskb_expand_head
+ether_setup
+param_ops_byte
+net_ratelimit
+round_jiffies_relative
+call_rcu_sched
+___pskb_trim
+crc32_be
+cfg80211_ref_bss
+__hw_addr_unsync
+ieee80211_amsdu_to_8023s
+dev_warn
+pm_qos_remove_notifier
+__aeabi_llsr
+ktime_get_ts64
+__sw_hweight16
+dev_queue_xmit
+__wait_rcu_gp
+eth_mac_addr
+crypto_alloc_base
+atomic64_read
+usb_anchor_urb
+cfg80211_rx_assoc_resp
+__hw_addr_init
+krealloc
+platform_device_put
+/* Mediatek 7601u/7603u */
+cfg80211_find_vendor_ie
+_kstrtol
+cfg80211_tdls_oper_request
+
+irq_set_irq_type
+gpiod_direction_input
+gpiod_to_irq
+complete_all
+
+i2c_get_adapter
+i2c_transfer
+
+fh_get_pts64
+fh_pmu_get_ptsl
+fh_pmu_get_ptsh
+fh_set_ac_mclk_rate
+fh_get_ac_mclk_rate
+
+fh_pmu_wdt_pause
+fh_pmu_wdt_resume
+fh_pmu_usb_utmi_rst
+fh_pmu_usb_phy_rst
+fh_pmu_usb_resume
+fh_pmu_sdc_reset
+fh_pmu_dwi2s_set_clk
+fh_pmu_eth_set_speed
+fh_pmu_eth_reset
+fh_pmu_mipi_reset
+fh_pmu_mipi_select
+fh_pmu_dvp_select
+fh_pmu_isp_reset
+fh_pmu_jpeg_reset
+fh_pmu_jpeg_hw_reset
+fh_pmu_veu_reset
+fh_pmu_internal_ephy_reset
+fh_pmu_ephy_sel
+fh_pmu_get_tsensor_init_data
+fh_pmu_set_sdc1_funcsel
+fh_pmu_arxc_write_A625_INT_RAWSTAT
+fh_pmu_arxc_read_ARM_INT_RAWSTAT
+fh_pmu_arxc_write_ARM_INT_RAWSTAT
+fh_pmu_arxc_read_ARM_INT_STAT
+fh_pmu_arxc_reset
+fh_pmu_arxc_kickoff
+/* wifi Hi3881 */
+skb_queue_head
+send_sig
+vfs_llseek
+_find_next_bit_le
+sg_next
+kobject_del
+kthread_bind
+skb_dequeue_tail
+_cond_resched
+pid_task
+kobject_uevent_env
+sg_alloc_table
+work_busy
+mmc_power_save_host
+mmc_power_restore_host
+send_sig_info
+__printk_ratelimit
+sg_free_table
+add_uevent_var
+vm_mmap_pgoff
+memparse
+
+vfs_stat
+clk_get_rate
diff --git a/ksyms_whitelists/fh8856v200_whitelist b/ksyms_whitelists/fh8856v200_whitelist
new file mode 100644
index 00000000..ce1fb608
--- /dev/null
+++ b/ksyms_whitelists/fh8856v200_whitelist
@@ -0,0 +1,671 @@
+__aeabi_idiv
+__aeabi_idivmod
+__aeabi_uidiv
+__aeabi_uidivmod
+__aeabi_unwind_cpp_pr1
+__class_create
+__init_waitqueue_head
+__kmalloc
+__msecs_to_jiffies
+__mutex_init
+__pv_phys_pfn_offset
+__wake_up
+alloc_chrdev_region
+anon_inode_getfd
+arm_copy_from_user
+arm_copy_to_user
+arm_delay_ops
+arm_dma_ops
+autoremove_wake_function
+cacheid
+cdev_add
+cdev_del
+cdev_init
+class_destroy
+clk_disable
+clk_enable
+clk_get
+clk_put
+clk_prepare
+clk_unprepare
+complete
+del_timer
+device_create
+device_destroy
+dma_alloc_from_coherent
+dma_release_from_coherent
+do_gettimeofday
+down
+fh_aes_128_ecb_encrypt
+fh_setscheduler
+fh_clk_enable
+fh_clk_get_rate
+fh_clk_set_rate
+fh_clk_prepare
+fh_clk_disable
+fh_clk_unprepare
+fh_clk_prepare_enable
+fh_clk_disable_unprepare
+fh_clk_set_parent
+fh_clk_get_parent
+fh_clk_has_parent
+fh_get_chipid
+fh_get_chipname
+fh_get_ddrsize_mbit
+fh_irq_create_mapping
+fh_mb_resize_maxdata
+fh_pmu_get_reg
+fh_pmu_set_reg
+fh_pmu_set_reg_m
+fh_setscheduler
+finish_wait
+free_irq
+get_chip_info
+high_memory
+init_timer_key
+init_wait_entry
+ioremap
+iounmap
+irq_create_mapping
+jiffies
+kfree
+kmalloc_caches
+kmalloc_order
+kmem_cache_alloc
+kmem_cache_create
+kmem_cache_destroy
+kmem_cache_free
+kthread_create_on_node
+kthread_should_stop
+kthread_stop
+memcpy
+memset
+misc_deregister
+misc_register
+mod_timer
+msleep
+mutex_lock
+mutex_lock_interruptible
+mutex_trylock
+mutex_unlock
+noop_llseek
+param_ops_int
+param_ops_string
+param_ops_uint
+pool_get_free_ex
+pool_get_use_size
+pool_put_free
+pool_put_use
+preempt_count_add
+preempt_count_sub
+preempt_schedule
+prepare_to_wait
+prepare_to_wait_event
+printk
+proc_create_data
+release_firmware
+remap_pfn_range
+remove_proc_entry
+request_firmware
+request_threaded_irq
+sched_setscheduler
+schedule
+schedule_timeout
+seq_open
+seq_printf
+seq_read
+seq_release
+simple_strtol
+simple_strtoul
+snprintf
+sprintf
+strcmp
+strcpy
+strlcpy
+strlen
+strncasecmp
+strncmp
+strncpy
+strnlen_user
+strsep
+unregister_chrdev_region
+up
+v6_flush_kern_cache_all
+v6_flush_kern_dcache_area
+vfree
+vm_mmap
+vmalloc
+vsnprintf
+wait_for_completion
+wait_for_completion_interruptible
+wake_up_process
+warn_slowpath_null
+fh_confidence_map_gen
+fh_drop_decide
+fh_drop_update
+fh_generate_smart_cfg_table
+fh_rc_Init
+fh_rc_change_param
+fh_rc_get_qp
+fh_rc_update
+fh_register_h264_callback
+fh_unregister_h264_callback
+fhk_mtrace
+fhk_trace
+generaterandseed
+get_pts
+get_pts64
+get_pts_rate
+get_ptsh_from_pts64
+get_ptsl_from_pts64
+jpeg_queue_get
+jpeg_queue_num
+jpeg_queue_put
+jpeg_queue_query
+meantime2fps
+meantime2fps_string
+media_close_low_power
+media_disable_clk
+media_disable_clk_flag_safe
+media_disable_clk_safe
+media_enable_clk_flag_safe
+media_enable_clk_safe
+media_encode_lock
+media_encode_unlock
+media_frmrate_status
+media_generatekey
+media_getbind
+media_info_find
+media_info_register
+media_info_unregister
+media_init_low_power
+media_is_low_power_mode
+media_malloc
+media_new_frame_wakeup
+media_object_register
+media_object_unregister
+media_query_encoder_need_stmsize
+media_query_malloc_stmsize
+media_stream_buff_malloc
+media_stream_buff_unmap
+media_stream_calc_addr
+media_stream_chn_size
+media_stream_get_info
+media_stream_mem_get_free
+media_stream_pool_to_queue
+media_stream_query
+media_stream_register
+media_stream_release
+media_stream_unregister
+media_uninit_low_power
+tms_end
+tms_get_avg
+tms_get_max
+tms_get_winsize
+tms_init
+tms_start
+vbus_mesg_deinit
+vbus_mesg_init
+vbus_mesg_initcallback
+vbus_mesg_write
+yuv_check_mem_range
+yuv_queue_get
+yuv_queue_num
+yuv_queue_put
+yuv_queue_query
+/* RTL8192FS */
+eth_type_trans
+single_release
+sdio_writew
+register_netdevice_notifier
+cfg80211_mgmt_tx_status
+sdio_writel
+proc_mkdir_data
+dev_get_by_name
+sdio_writeb
+wiphy_apply_custom_regulatory
+ieee80211_frequency_to_channel
+sdio_memcpy_fromio
+cfg80211_rx_mgmt
+kern_path
+free_netdev
+__cfg80211_alloc_reply_skb
+__csum_ipv6_magic
+unregister_netdevice_queue
+system_wq
+__pskb_copy_fclone
+sdio_release_host
+yield
+ktime_get_with_offset
+register_inet6addr_notifier
+sdio_release_irq
+print_hex_dump
+alloc_etherdev_mqs
+cfg80211_new_sta
+sdio_set_host_pm_flags
+unregister_netdev
+sdio_get_host_pm_caps
+flush_signals
+unregister_netdevice_notifier
+cfg80211_inform_bss_frame_data
+dev_alloc_name
+__local_bh_enable_ip
+netif_carrier_on
+cfg80211_unlink_bss
+__dev_kfree_skb_any
+find_vpid
+sdio_set_block_size
+skb_push
+wait_for_completion_timeout
+__usecs_to_jiffies
+dev_err
+kernel_sigaction
+single_open_size
+kill_pid
+skb_trim
+unregister_inetaddr_notifier
+_test_and_clear_bit
+sdio_enable_func
+register_netdev
+sdio_memcpy_toio
+sdio_writesb
+cfg80211_put_bss
+cfg80211_roamed
+register_inetaddr_notifier
+cfg80211_scan_done
+sdio_claim_irq
+sdio_readb
+sdio_register_driver
+netif_carrier_off
+ns_to_timespec
+__vfs_read
+_set_bit
+_clear_bit
+register_netdevice
+seq_lseek
+PDE_DATA
+skb_copy
+param_ops_charp
+skb_copy_bits
+cfg80211_ibss_joined
+netif_rx
+tasklet_kill
+skb_dequeue
+cfg80211_michael_mic_failure
+netif_tx_wake_queue
+complete_and_exit
+cfg80211_disconnected
+prandom_u32
+strpbrk
+init_net
+__cfg80211_send_event_skb
+strchr
+sdio_claim_host
+sdio_readw
+cfg80211_get_bss
+wiphy_new_nm
+param_array_ops
+wiphy_free
+queue_work_on
+sdio_readl
+sdio_unregister_driver
+down_interruptible
+proc_get_parent_data
+__vfs_write
+sdio_readsb
+sdio_disable_func
+skb_put
+__ieee80211_get_channel
+csum_partial
+cfg80211_ready_on_channel
+usleep_range
+__do_div64
+skb_clone
+filp_close
+memmove
+cfg80211_ch_switch_notify
+netif_wake_subqueue
+single_open
+__pskb_pull_tail
+cfg80211_connect_bss
+jiffies_to_msecs
+filp_open
+wiphy_unregister
+netif_tx_stop_all_queues
+cfg80211_del_sta_sinfo
+tasklet_init
+sdio_f0_writeb
+cfg80211_vendor_cmd_reply
+__tasklet_schedule
+sscanf
+sdio_f0_readb
+__netdev_alloc_skb
+nla_put_nohdr
+cfg80211_remain_on_channel_expired
+nla_put
+wiphy_register
+__cfg80211_alloc_event_skb
+memcmp
+unregister_inet6addr_notifier
+rtnl_is_locked
+skb_pull
+/* AtbmWifi */
+netdev_master_upper_dev_get_rcu
+usb_find_interface
+full_name_hash
+schedule_timeout_interruptible
+scnprintf
+usb_anchor_empty
+usb_for_each_dev
+/* Cypress 43438/43455 */
+disable_irq
+disable_irq_nosync
+irq_set_irq_wake
+enable_irq
+_change_bit
+fh_pinctrl_sdev
+sg_init_table
+__kfifo_out
+generic_file_llseek
+mem_map
+strspn
+get_random_bytes
+remove_wait_queue
+rtnl_lock
+gpio_request
+cfg80211_chandef_create
+gpio_to_desc
+delayed_work_timer_fn
+cancel_work_sync
+platform_bus_type
+kmemdup
+ieee80211_channel_to_frequency
+cancel_delayed_work_sync
+rfkill_register
+cfg80211_unregister_wdev
+skb_realloc_headroom
+__platform_driver_register
+__kfifo_init
+default_wake_function
+mmc_wait_for_req
+kernel_read
+netif_rx_ni
+rfkill_alloc
+netlink_kernel_release
+strcasecmp
+mmc_set_data_timeout
+register_pm_notifier
+dev_close
+strstr
+synchronize_sched
+netlink_unicast
+add_timer
+gpiod_direction_output_raw
+bus_find_device
+device_init_wakeup
+sort
+strcat
+unregister_reboot_notifier
+capable
+strrchr
+__alloc_skb
+fh_sdio_card_scan
+register_reboot_notifier
+queue_delayed_work_on
+sched_clock
+jiffies_to_usecs
+__kfifo_free
+platform_get_resource_byname
+cfg80211_find_ie_match
+gpio_free
+__netlink_kernel_create
+add_wait_queue
+pm_stay_awake
+rfkill_destroy
+unregister_pm_notifier
+pm_relax
+__kfifo_in
+consume_skb
+platform_driver_unregister
+rfkill_unregister
+__nlmsg_put
+down_timeout
+rtnl_unlock
+/* sdio Marvell 8801 */
+iw_handler_set_thrspy
+__alloc_workqueue_key
+cfg80211_inform_bss_data
+cfg80211_report_wowlan_wakeup
+cfg80211_pmksa_candidate_notify
+proc_mkdir
+_ctype
+iw_handler_get_spy
+panic
+wireless_send_event
+vprintk
+destroy_workqueue
+request_firmware_nowait
+up_write
+flush_workqueue
+ieee80211_bss_get_ie
+module_put
+netif_device_attach
+netif_device_detach
+hex_dump_to_buffer
+netlink_broadcast
+iw_handler_get_thrspy
+in4_pton
+dump_stack
+vfs_mkdir
+kern_path_create
+eth_validate_addr
+iw_handler_set_spy
+regulatory_hint
+cfg80211_sched_scan_stopped
+dev_set_name
+strim
+try_module_get
+device_set_wakeup_enable
+vfs_write
+cfg80211_sched_scan_results
+/* Realtek 8189ftv */
+__napi_schedule
+napi_gro_receive
+skb_queue_tail
+napi_disable
+netif_receive_skb
+netif_napi_add
+napi_complete_done
+netif_napi_del
+/* usb Marvell 8801 */
+usb_init_urb
+system_freezing_cnt
+usb_kill_urb
+usb_enable_autosuspend
+usb_disable_autosuspend
+freezing_slow_path
+strncat
+usb_deregister
+usb_submit_urb
+usb_get_dev
+usb_reset_device
+usb_bulk_msg
+usb_put_dev
+__refrigerator
+usb_register_driver
+pm_runtime_set_autosuspend_delay
+usb_free_urb
+usb_alloc_urb
+/* RTL8188FTV */
+usb_alloc_coherent
+__tasklet_hi_schedule
+usb_control_msg
+usb_autopm_get_interface
+usb_free_coherent
+init_dummy_netdev
+cfg80211_sched_scan_stopped_rtnl
+nla_parse
+getrawmonotonic64
+param_ops_ushort
+usb_autopm_put_interface
+/* ATBM6032 */
+synchronize_net
+_find_first_bit_le
+cfg80211_rx_unprot_mlme_mgmt
+cfg80211_auth_timeout
+kobject_put
+flush_work
+__request_module
+cfg80211_cqm_rssi_notify
+pm_qos_request
+usb_wait_anchor_empty_timeout
+round_jiffies
+bridge_tunnel_header
+schedule_timeout_uninterruptible
+skb_pad
+_find_first_zero_bit_le
+dev_printk
+ieee80211_hdrlen
+__aeabi_llsl
+ieee80211_radiotap_iterator_next
+usb_unlink_urb
+sysfs_remove_group
+kobject_create_and_add
+usb_unanchor_urb
+usb_block_urb
+__hw_addr_sync
+vfs_read
+rfc1042_header
+skb_queue_purge
+kernel_param_unlock
+cancel_delayed_work
+unregister_netdevice_many
+usb_lock_device_for_reset
+down_trylock
+print_hex_dump_bytes
+sysfs_create_group
+ieee80211_data_to_8023_exthdr
+ieee80211_radiotap_iterator_init
+nla_find
+platform_device_alloc
+pm_qos_add_notifier
+usb_unpoison_urb
+platform_device_add
+crc32_le
+cfg80211_cqm_pktloss_notify
+__dev_kfree_skb_irq
+platform_device_unregister
+cfg80211_report_obss_beacon
+memchr
+cfg80211_rx_spurious_frame
+kernel_param_lock
+cfg80211_assoc_timeout
+__sw_hweight64
+skb_copy_expand
+cfg80211_gtk_rekey_notify
+_dev_info
+cfg80211_tx_mlme_mgmt
+cfg80211_rx_mlme_mgmt
+cfg80211_classify8021d
+kfree_skb
+flush_delayed_work
+alloc_netdev_mqs
+atomic64_add_return
+crypto_destroy_tfm
+round_jiffies_up
+pskb_expand_head
+ether_setup
+param_ops_byte
+net_ratelimit
+round_jiffies_relative
+call_rcu_sched
+___pskb_trim
+crc32_be
+cfg80211_ref_bss
+__hw_addr_unsync
+ieee80211_amsdu_to_8023s
+dev_warn
+pm_qos_remove_notifier
+__aeabi_llsr
+ktime_get_ts64
+__sw_hweight16
+dev_queue_xmit
+__wait_rcu_gp
+eth_mac_addr
+crypto_alloc_base
+atomic64_read
+usb_anchor_urb
+cfg80211_rx_assoc_resp
+__hw_addr_init
+krealloc
+platform_device_put
+/* Mediatek 7601u/7603u */
+cfg80211_find_vendor_ie
+_kstrtol
+cfg80211_tdls_oper_request
+
+irq_set_irq_type
+gpiod_direction_input
+gpiod_to_irq
+complete_all
+
+i2c_get_adapter
+i2c_transfer
+
+fh_get_pts64
+fh_pmu_get_ptsl
+fh_pmu_get_ptsh
+fh_set_ac_mclk_rate
+fh_get_ac_mclk_rate
+
+fh_pmu_wdt_pause
+fh_pmu_wdt_resume
+fh_pmu_usb_utmi_rst
+fh_pmu_usb_phy_rst
+fh_pmu_usb_resume
+fh_pmu_sdc_reset
+fh_pmu_dwi2s_set_clk
+fh_pmu_eth_set_speed
+fh_pmu_eth_reset
+fh_pmu_mipi_reset
+fh_pmu_mipi_select
+fh_pmu_dvp_select
+fh_pmu_isp_reset
+fh_pmu_jpeg_reset
+fh_pmu_jpeg_hw_reset
+fh_pmu_veu_reset
+fh_pmu_internal_ephy_reset
+fh_pmu_ephy_sel
+fh_pmu_get_tsensor_init_data
+fh_pmu_set_sdc1_funcsel
+fh_pmu_arxc_write_A625_INT_RAWSTAT
+fh_pmu_arxc_read_ARM_INT_RAWSTAT
+fh_pmu_arxc_write_ARM_INT_RAWSTAT
+fh_pmu_arxc_read_ARM_INT_STAT
+fh_pmu_arxc_reset
+fh_pmu_arxc_kickoff
+/* wifi Hi3881 */
+skb_queue_head
+send_sig
+vfs_llseek
+_find_next_bit_le
+sg_next
+kobject_del
+kthread_bind
+skb_dequeue_tail
+_cond_resched
+pid_task
+kobject_uevent_env
+sg_alloc_table
+work_busy
+mmc_power_save_host
+mmc_power_restore_host
+send_sig_info
+__printk_ratelimit
+sg_free_table
+add_uevent_var
+vm_mmap_pgoff
+memparse
+
+vfs_stat
+clk_get_rate
diff --git a/ksyms_whitelists/fh8858v200_whitelist b/ksyms_whitelists/fh8858v200_whitelist
new file mode 100644
index 00000000..ce1fb608
--- /dev/null
+++ b/ksyms_whitelists/fh8858v200_whitelist
@@ -0,0 +1,671 @@
+__aeabi_idiv
+__aeabi_idivmod
+__aeabi_uidiv
+__aeabi_uidivmod
+__aeabi_unwind_cpp_pr1
+__class_create
+__init_waitqueue_head
+__kmalloc
+__msecs_to_jiffies
+__mutex_init
+__pv_phys_pfn_offset
+__wake_up
+alloc_chrdev_region
+anon_inode_getfd
+arm_copy_from_user
+arm_copy_to_user
+arm_delay_ops
+arm_dma_ops
+autoremove_wake_function
+cacheid
+cdev_add
+cdev_del
+cdev_init
+class_destroy
+clk_disable
+clk_enable
+clk_get
+clk_put
+clk_prepare
+clk_unprepare
+complete
+del_timer
+device_create
+device_destroy
+dma_alloc_from_coherent
+dma_release_from_coherent
+do_gettimeofday
+down
+fh_aes_128_ecb_encrypt
+fh_setscheduler
+fh_clk_enable
+fh_clk_get_rate
+fh_clk_set_rate
+fh_clk_prepare
+fh_clk_disable
+fh_clk_unprepare
+fh_clk_prepare_enable
+fh_clk_disable_unprepare
+fh_clk_set_parent
+fh_clk_get_parent
+fh_clk_has_parent
+fh_get_chipid
+fh_get_chipname
+fh_get_ddrsize_mbit
+fh_irq_create_mapping
+fh_mb_resize_maxdata
+fh_pmu_get_reg
+fh_pmu_set_reg
+fh_pmu_set_reg_m
+fh_setscheduler
+finish_wait
+free_irq
+get_chip_info
+high_memory
+init_timer_key
+init_wait_entry
+ioremap
+iounmap
+irq_create_mapping
+jiffies
+kfree
+kmalloc_caches
+kmalloc_order
+kmem_cache_alloc
+kmem_cache_create
+kmem_cache_destroy
+kmem_cache_free
+kthread_create_on_node
+kthread_should_stop
+kthread_stop
+memcpy
+memset
+misc_deregister
+misc_register
+mod_timer
+msleep
+mutex_lock
+mutex_lock_interruptible
+mutex_trylock
+mutex_unlock
+noop_llseek
+param_ops_int
+param_ops_string
+param_ops_uint
+pool_get_free_ex
+pool_get_use_size
+pool_put_free
+pool_put_use
+preempt_count_add
+preempt_count_sub
+preempt_schedule
+prepare_to_wait
+prepare_to_wait_event
+printk
+proc_create_data
+release_firmware
+remap_pfn_range
+remove_proc_entry
+request_firmware
+request_threaded_irq
+sched_setscheduler
+schedule
+schedule_timeout
+seq_open
+seq_printf
+seq_read
+seq_release
+simple_strtol
+simple_strtoul
+snprintf
+sprintf
+strcmp
+strcpy
+strlcpy
+strlen
+strncasecmp
+strncmp
+strncpy
+strnlen_user
+strsep
+unregister_chrdev_region
+up
+v6_flush_kern_cache_all
+v6_flush_kern_dcache_area
+vfree
+vm_mmap
+vmalloc
+vsnprintf
+wait_for_completion
+wait_for_completion_interruptible
+wake_up_process
+warn_slowpath_null
+fh_confidence_map_gen
+fh_drop_decide
+fh_drop_update
+fh_generate_smart_cfg_table
+fh_rc_Init
+fh_rc_change_param
+fh_rc_get_qp
+fh_rc_update
+fh_register_h264_callback
+fh_unregister_h264_callback
+fhk_mtrace
+fhk_trace
+generaterandseed
+get_pts
+get_pts64
+get_pts_rate
+get_ptsh_from_pts64
+get_ptsl_from_pts64
+jpeg_queue_get
+jpeg_queue_num
+jpeg_queue_put
+jpeg_queue_query
+meantime2fps
+meantime2fps_string
+media_close_low_power
+media_disable_clk
+media_disable_clk_flag_safe
+media_disable_clk_safe
+media_enable_clk_flag_safe
+media_enable_clk_safe
+media_encode_lock
+media_encode_unlock
+media_frmrate_status
+media_generatekey
+media_getbind
+media_info_find
+media_info_register
+media_info_unregister
+media_init_low_power
+media_is_low_power_mode
+media_malloc
+media_new_frame_wakeup
+media_object_register
+media_object_unregister
+media_query_encoder_need_stmsize
+media_query_malloc_stmsize
+media_stream_buff_malloc
+media_stream_buff_unmap
+media_stream_calc_addr
+media_stream_chn_size
+media_stream_get_info
+media_stream_mem_get_free
+media_stream_pool_to_queue
+media_stream_query
+media_stream_register
+media_stream_release
+media_stream_unregister
+media_uninit_low_power
+tms_end
+tms_get_avg
+tms_get_max
+tms_get_winsize
+tms_init
+tms_start
+vbus_mesg_deinit
+vbus_mesg_init
+vbus_mesg_initcallback
+vbus_mesg_write
+yuv_check_mem_range
+yuv_queue_get
+yuv_queue_num
+yuv_queue_put
+yuv_queue_query
+/* RTL8192FS */
+eth_type_trans
+single_release
+sdio_writew
+register_netdevice_notifier
+cfg80211_mgmt_tx_status
+sdio_writel
+proc_mkdir_data
+dev_get_by_name
+sdio_writeb
+wiphy_apply_custom_regulatory
+ieee80211_frequency_to_channel
+sdio_memcpy_fromio
+cfg80211_rx_mgmt
+kern_path
+free_netdev
+__cfg80211_alloc_reply_skb
+__csum_ipv6_magic
+unregister_netdevice_queue
+system_wq
+__pskb_copy_fclone
+sdio_release_host
+yield
+ktime_get_with_offset
+register_inet6addr_notifier
+sdio_release_irq
+print_hex_dump
+alloc_etherdev_mqs
+cfg80211_new_sta
+sdio_set_host_pm_flags
+unregister_netdev
+sdio_get_host_pm_caps
+flush_signals
+unregister_netdevice_notifier
+cfg80211_inform_bss_frame_data
+dev_alloc_name
+__local_bh_enable_ip
+netif_carrier_on
+cfg80211_unlink_bss
+__dev_kfree_skb_any
+find_vpid
+sdio_set_block_size
+skb_push
+wait_for_completion_timeout
+__usecs_to_jiffies
+dev_err
+kernel_sigaction
+single_open_size
+kill_pid
+skb_trim
+unregister_inetaddr_notifier
+_test_and_clear_bit
+sdio_enable_func
+register_netdev
+sdio_memcpy_toio
+sdio_writesb
+cfg80211_put_bss
+cfg80211_roamed
+register_inetaddr_notifier
+cfg80211_scan_done
+sdio_claim_irq
+sdio_readb
+sdio_register_driver
+netif_carrier_off
+ns_to_timespec
+__vfs_read
+_set_bit
+_clear_bit
+register_netdevice
+seq_lseek
+PDE_DATA
+skb_copy
+param_ops_charp
+skb_copy_bits
+cfg80211_ibss_joined
+netif_rx
+tasklet_kill
+skb_dequeue
+cfg80211_michael_mic_failure
+netif_tx_wake_queue
+complete_and_exit
+cfg80211_disconnected
+prandom_u32
+strpbrk
+init_net
+__cfg80211_send_event_skb
+strchr
+sdio_claim_host
+sdio_readw
+cfg80211_get_bss
+wiphy_new_nm
+param_array_ops
+wiphy_free
+queue_work_on
+sdio_readl
+sdio_unregister_driver
+down_interruptible
+proc_get_parent_data
+__vfs_write
+sdio_readsb
+sdio_disable_func
+skb_put
+__ieee80211_get_channel
+csum_partial
+cfg80211_ready_on_channel
+usleep_range
+__do_div64
+skb_clone
+filp_close
+memmove
+cfg80211_ch_switch_notify
+netif_wake_subqueue
+single_open
+__pskb_pull_tail
+cfg80211_connect_bss
+jiffies_to_msecs
+filp_open
+wiphy_unregister
+netif_tx_stop_all_queues
+cfg80211_del_sta_sinfo
+tasklet_init
+sdio_f0_writeb
+cfg80211_vendor_cmd_reply
+__tasklet_schedule
+sscanf
+sdio_f0_readb
+__netdev_alloc_skb
+nla_put_nohdr
+cfg80211_remain_on_channel_expired
+nla_put
+wiphy_register
+__cfg80211_alloc_event_skb
+memcmp
+unregister_inet6addr_notifier
+rtnl_is_locked
+skb_pull
+/* AtbmWifi */
+netdev_master_upper_dev_get_rcu
+usb_find_interface
+full_name_hash
+schedule_timeout_interruptible
+scnprintf
+usb_anchor_empty
+usb_for_each_dev
+/* Cypress 43438/43455 */
+disable_irq
+disable_irq_nosync
+irq_set_irq_wake
+enable_irq
+_change_bit
+fh_pinctrl_sdev
+sg_init_table
+__kfifo_out
+generic_file_llseek
+mem_map
+strspn
+get_random_bytes
+remove_wait_queue
+rtnl_lock
+gpio_request
+cfg80211_chandef_create
+gpio_to_desc
+delayed_work_timer_fn
+cancel_work_sync
+platform_bus_type
+kmemdup
+ieee80211_channel_to_frequency
+cancel_delayed_work_sync
+rfkill_register
+cfg80211_unregister_wdev
+skb_realloc_headroom
+__platform_driver_register
+__kfifo_init
+default_wake_function
+mmc_wait_for_req
+kernel_read
+netif_rx_ni
+rfkill_alloc
+netlink_kernel_release
+strcasecmp
+mmc_set_data_timeout
+register_pm_notifier
+dev_close
+strstr
+synchronize_sched
+netlink_unicast
+add_timer
+gpiod_direction_output_raw
+bus_find_device
+device_init_wakeup
+sort
+strcat
+unregister_reboot_notifier
+capable
+strrchr
+__alloc_skb
+fh_sdio_card_scan
+register_reboot_notifier
+queue_delayed_work_on
+sched_clock
+jiffies_to_usecs
+__kfifo_free
+platform_get_resource_byname
+cfg80211_find_ie_match
+gpio_free
+__netlink_kernel_create
+add_wait_queue
+pm_stay_awake
+rfkill_destroy
+unregister_pm_notifier
+pm_relax
+__kfifo_in
+consume_skb
+platform_driver_unregister
+rfkill_unregister
+__nlmsg_put
+down_timeout
+rtnl_unlock
+/* sdio Marvell 8801 */
+iw_handler_set_thrspy
+__alloc_workqueue_key
+cfg80211_inform_bss_data
+cfg80211_report_wowlan_wakeup
+cfg80211_pmksa_candidate_notify
+proc_mkdir
+_ctype
+iw_handler_get_spy
+panic
+wireless_send_event
+vprintk
+destroy_workqueue
+request_firmware_nowait
+up_write
+flush_workqueue
+ieee80211_bss_get_ie
+module_put
+netif_device_attach
+netif_device_detach
+hex_dump_to_buffer
+netlink_broadcast
+iw_handler_get_thrspy
+in4_pton
+dump_stack
+vfs_mkdir
+kern_path_create
+eth_validate_addr
+iw_handler_set_spy
+regulatory_hint
+cfg80211_sched_scan_stopped
+dev_set_name
+strim
+try_module_get
+device_set_wakeup_enable
+vfs_write
+cfg80211_sched_scan_results
+/* Realtek 8189ftv */
+__napi_schedule
+napi_gro_receive
+skb_queue_tail
+napi_disable
+netif_receive_skb
+netif_napi_add
+napi_complete_done
+netif_napi_del
+/* usb Marvell 8801 */
+usb_init_urb
+system_freezing_cnt
+usb_kill_urb
+usb_enable_autosuspend
+usb_disable_autosuspend
+freezing_slow_path
+strncat
+usb_deregister
+usb_submit_urb
+usb_get_dev
+usb_reset_device
+usb_bulk_msg
+usb_put_dev
+__refrigerator
+usb_register_driver
+pm_runtime_set_autosuspend_delay
+usb_free_urb
+usb_alloc_urb
+/* RTL8188FTV */
+usb_alloc_coherent
+__tasklet_hi_schedule
+usb_control_msg
+usb_autopm_get_interface
+usb_free_coherent
+init_dummy_netdev
+cfg80211_sched_scan_stopped_rtnl
+nla_parse
+getrawmonotonic64
+param_ops_ushort
+usb_autopm_put_interface
+/* ATBM6032 */
+synchronize_net
+_find_first_bit_le
+cfg80211_rx_unprot_mlme_mgmt
+cfg80211_auth_timeout
+kobject_put
+flush_work
+__request_module
+cfg80211_cqm_rssi_notify
+pm_qos_request
+usb_wait_anchor_empty_timeout
+round_jiffies
+bridge_tunnel_header
+schedule_timeout_uninterruptible
+skb_pad
+_find_first_zero_bit_le
+dev_printk
+ieee80211_hdrlen
+__aeabi_llsl
+ieee80211_radiotap_iterator_next
+usb_unlink_urb
+sysfs_remove_group
+kobject_create_and_add
+usb_unanchor_urb
+usb_block_urb
+__hw_addr_sync
+vfs_read
+rfc1042_header
+skb_queue_purge
+kernel_param_unlock
+cancel_delayed_work
+unregister_netdevice_many
+usb_lock_device_for_reset
+down_trylock
+print_hex_dump_bytes
+sysfs_create_group
+ieee80211_data_to_8023_exthdr
+ieee80211_radiotap_iterator_init
+nla_find
+platform_device_alloc
+pm_qos_add_notifier
+usb_unpoison_urb
+platform_device_add
+crc32_le
+cfg80211_cqm_pktloss_notify
+__dev_kfree_skb_irq
+platform_device_unregister
+cfg80211_report_obss_beacon
+memchr
+cfg80211_rx_spurious_frame
+kernel_param_lock
+cfg80211_assoc_timeout
+__sw_hweight64
+skb_copy_expand
+cfg80211_gtk_rekey_notify
+_dev_info
+cfg80211_tx_mlme_mgmt
+cfg80211_rx_mlme_mgmt
+cfg80211_classify8021d
+kfree_skb
+flush_delayed_work
+alloc_netdev_mqs
+atomic64_add_return
+crypto_destroy_tfm
+round_jiffies_up
+pskb_expand_head
+ether_setup
+param_ops_byte
+net_ratelimit
+round_jiffies_relative
+call_rcu_sched
+___pskb_trim
+crc32_be
+cfg80211_ref_bss
+__hw_addr_unsync
+ieee80211_amsdu_to_8023s
+dev_warn
+pm_qos_remove_notifier
+__aeabi_llsr
+ktime_get_ts64
+__sw_hweight16
+dev_queue_xmit
+__wait_rcu_gp
+eth_mac_addr
+crypto_alloc_base
+atomic64_read
+usb_anchor_urb
+cfg80211_rx_assoc_resp
+__hw_addr_init
+krealloc
+platform_device_put
+/* Mediatek 7601u/7603u */
+cfg80211_find_vendor_ie
+_kstrtol
+cfg80211_tdls_oper_request
+
+irq_set_irq_type
+gpiod_direction_input
+gpiod_to_irq
+complete_all
+
+i2c_get_adapter
+i2c_transfer
+
+fh_get_pts64
+fh_pmu_get_ptsl
+fh_pmu_get_ptsh
+fh_set_ac_mclk_rate
+fh_get_ac_mclk_rate
+
+fh_pmu_wdt_pause
+fh_pmu_wdt_resume
+fh_pmu_usb_utmi_rst
+fh_pmu_usb_phy_rst
+fh_pmu_usb_resume
+fh_pmu_sdc_reset
+fh_pmu_dwi2s_set_clk
+fh_pmu_eth_set_speed
+fh_pmu_eth_reset
+fh_pmu_mipi_reset
+fh_pmu_mipi_select
+fh_pmu_dvp_select
+fh_pmu_isp_reset
+fh_pmu_jpeg_reset
+fh_pmu_jpeg_hw_reset
+fh_pmu_veu_reset
+fh_pmu_internal_ephy_reset
+fh_pmu_ephy_sel
+fh_pmu_get_tsensor_init_data
+fh_pmu_set_sdc1_funcsel
+fh_pmu_arxc_write_A625_INT_RAWSTAT
+fh_pmu_arxc_read_ARM_INT_RAWSTAT
+fh_pmu_arxc_write_ARM_INT_RAWSTAT
+fh_pmu_arxc_read_ARM_INT_STAT
+fh_pmu_arxc_reset
+fh_pmu_arxc_kickoff
+/* wifi Hi3881 */
+skb_queue_head
+send_sig
+vfs_llseek
+_find_next_bit_le
+sg_next
+kobject_del
+kthread_bind
+skb_dequeue_tail
+_cond_resched
+pid_task
+kobject_uevent_env
+sg_alloc_table
+work_busy
+mmc_power_save_host
+mmc_power_restore_host
+send_sig_info
+__printk_ratelimit
+sg_free_table
+add_uevent_var
+vm_mmap_pgoff
+memparse
+
+vfs_stat
+clk_get_rate
diff --git a/lib/Kconfig b/lib/Kconfig
index 260a80e3..8c557103 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -184,6 +184,8 @@ config CRC8
This option provides CRC8 function. Drivers may select this
when they need to do cyclic redundancy check according CRC8
algorithm. Module will be called crc8.
+config HALFMD4
+ bool
config AUDIT_GENERIC
bool
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 58a22ca1..61cc99b3 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -283,6 +283,20 @@ config HEADERS_CHECK
exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
your build tree), to make sure they're suitable.
+config OPTIMIZE_INLINING
+ bool "Allow compiler to uninline functions marked 'inline'"
+ help
+ This option determines if the kernel forces gcc to inline the functions
+ developers have marked 'inline'. Doing so takes away freedom from gcc to
+ do what it thinks is best, which is desirable for the gcc 3.x series of
+ compilers. The gcc 4.x series have a rewritten inlining algorithm and
+ enabling this option will generate a smaller kernel there. Hopefully
+ this algorithm is so good that allowing gcc 4.x and above to make the
+ decision will become the default in the future. Until then this option
+ is there to test gcc for this.
+
+ If unsure, say N.
+
config DEBUG_SECTION_MISMATCH
bool "Enable full Section mismatch analysis"
help
diff --git a/lib/Makefile b/lib/Makefile
index 50144a3a..eeec4d60 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -31,12 +31,13 @@ lib-$(CONFIG_HAS_DMA) += dma-noop.o
lib-y += kobject.o klist.o
obj-y += lockref.o
-obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
+obj-y += bcd.o div64.o sort.o parser.o debug_locks.o random32.o \
bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
gcd.o lcm.o list_sort.o uuid.o flex_array.o iov_iter.o clz_ctz.o \
bsearch.o find_bit.o llist.o memweight.o kfifo.o \
percpu-refcount.o percpu_ida.o rhashtable.o reciprocal_div.o \
once.o
+obj-$(CONFIG_HALFMD4) += halfmd4.o
obj-y += string_helpers.o
obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
obj-y += hexdump.o
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 851efb00..1a10dc2f 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1704,19 +1704,17 @@ static int soft_offline_in_use_page(struct page *page, int flags)
struct page *hpage = compound_head(page);
if (!PageHuge(page) && PageTransHuge(hpage)) {
- lock_page(hpage);
- if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) {
- unlock_page(hpage);
- if (!PageAnon(hpage))
+ lock_page(page);
+ if (!PageAnon(page) || unlikely(split_huge_page(page))) {
+ unlock_page(page);
+ if (!PageAnon(page))
pr_info("soft offline: %#lx: non anonymous thp\n", page_to_pfn(page));
else
pr_info("soft offline: %#lx: thp split failed\n", page_to_pfn(page));
- put_hwpoison_page(hpage);
+ put_hwpoison_page(page);
return -EBUSY;
}
- unlock_page(hpage);
- get_hwpoison_page(page);
- put_hwpoison_page(hpage);
+ unlock_page(page);
}
if (PageHuge(page))
diff --git a/mm/mmap.c b/mm/mmap.c
index aa97074a..1f43209b 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1376,7 +1376,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
return -ENOMEM;
/* offset overflow? */
- if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
+ if (((phys_addr_t)pgoff + (len >> PAGE_SHIFT)) < (phys_addr_t)pgoff)
return -EOVERFLOW;
/* Too many mappings? */
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 6896f77b..6a97c29e 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -152,8 +152,17 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
unsigned long this_pages;
next = pmd_addr_end(addr, end);
- if (!pmd_trans_huge(*pmd) && !pmd_devmap(*pmd)
- && pmd_none_or_clear_bad(pmd))
+
+ /*
+ * Automatic NUMA balancing walks the tables with mmap_sem
+ * held for read. It's possible a parallel udate
+ * to occur between pmd_trans_huge and a pmd_none_or_clear_bad
+ * check leading to a false positive and clearing. Hence, it's
+ * necessary to atomically read the PMD value for all the
+ * checks.
+ */
+ if (!pmd_devmap(*pmd) &&
+ pmd_none_or_clear_bad_unless_trans_huge(pmd))
continue;
/* invoke the mmu notifier if the pmd is populated */
diff --git a/mm/slub.c b/mm/slub.c
index e0ce5dec..56b2d9b2 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5714,7 +5714,11 @@ static int __init slab_sysfs_init(void)
return 0;
}
+#ifdef CONFIG_DEFERRED_INIICALLS_SLAB_SYSFS
+deferred_initcall(slab_sysfs_init);
+#else
__initcall(slab_sysfs_init);
+#endif
#endif /* CONFIG_SYSFS */
/*
diff --git a/mm/util.c b/mm/util.c
index 8c755d05..ff2b9232 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -334,6 +334,7 @@ unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
}
return ret;
}
+EXPORT_SYMBOL(vm_mmap_pgoff);
unsigned long vm_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index af46bc49..b5f84f42 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -293,7 +293,7 @@ int __init atalk_proc_init(void)
goto out;
}
-void __exit atalk_proc_exit(void)
+void atalk_proc_exit(void)
{
remove_proc_entry("interface", atalk_proc_dir);
remove_proc_entry("route", atalk_proc_dir);
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 10d2bdce..2d79ba06 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1912,12 +1912,16 @@ static const char atalk_err_snap[] __initconst =
/* Called by proto.c on kernel start up */
static int __init atalk_init(void)
{
- int rc = proto_register(&ddp_proto, 0);
+ int rc;
- if (rc != 0)
+ rc = proto_register(&ddp_proto, 0);
+ if (rc)
goto out;
- (void)sock_register(&atalk_family_ops);
+ rc = sock_register(&atalk_family_ops);
+ if (rc)
+ goto out_proto;
+
ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv);
if (!ddp_dl)
printk(atalk_err_snap);
@@ -1925,12 +1929,34 @@ static int __init atalk_init(void)
dev_add_pack(&ltalk_packet_type);
dev_add_pack(&ppptalk_packet_type);
- register_netdevice_notifier(&ddp_notifier);
+ rc = register_netdevice_notifier(&ddp_notifier);
+ if (rc)
+ goto out_sock;
+
aarp_proto_init();
- atalk_proc_init();
- atalk_register_sysctl();
+ rc = atalk_proc_init();
+ if (rc)
+ goto out_aarp;
+
+ rc = atalk_register_sysctl();
+ if (rc)
+ goto out_proc;
out:
return rc;
+out_proc:
+ atalk_proc_exit();
+out_aarp:
+ aarp_cleanup_module();
+ unregister_netdevice_notifier(&ddp_notifier);
+out_sock:
+ dev_remove_pack(&ppptalk_packet_type);
+ dev_remove_pack(&ltalk_packet_type);
+ unregister_snap_client(ddp_dl);
+ sock_unregister(PF_APPLETALK);
+out_proto:
+ proto_unregister(&ddp_proto);
+ goto out;
+
}
module_init(atalk_init);
diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
index ebb86436..4e6042e0 100644
--- a/net/appletalk/sysctl_net_atalk.c
+++ b/net/appletalk/sysctl_net_atalk.c
@@ -44,9 +44,12 @@ static struct ctl_table atalk_table[] = {
static struct ctl_table_header *atalk_table_header;
-void atalk_register_sysctl(void)
+int __init atalk_register_sysctl(void)
{
atalk_table_header = register_net_sysctl(&init_net, "net/appletalk", atalk_table);
+ if (!atalk_table_header)
+ return -ENOMEM;
+ return 0;
}
void atalk_unregister_sysctl(void)
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index d36effbf..2daba531 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -527,7 +527,7 @@ static void rds_tcp_kill_sock(struct net *net)
list_for_each_entry_safe(tc, _tc, &rds_tcp_conn_list, t_tcp_node) {
struct net *c_net = read_pnet(&tc->t_cpath->cp_conn->c_net);
- if (net != c_net || !tc->t_sock)
+ if (net != c_net)
continue;
if (!list_has_conn(&tmp_list, tc->t_cpath->cp_conn)) {
list_move_tail(&tc->t_tcp_node, &tmp_list);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5dbac374..00f9e68c 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -222,13 +222,19 @@ static const struct ieee80211_regdomain world_regdom = {
/* IEEE 802.11b/g, channels 1..11 */
REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
/* IEEE 802.11b/g, channels 12..13. */
- REG_RULE(2467-10, 2472+10, 20, 6, 20,
- NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW),
+ REG_RULE(2467-10, 2472+10, 40, 6, 20,
+ #if 0
+ NL80211_RRF_NO_IR | NL80211_RRF_AUTO_BW
+ #endif
+ 0),
/* IEEE 802.11 channel 14 - Only JP enables
* this and for 802.11b only */
REG_RULE(2484-10, 2484+10, 20, 6, 20,
+ #if 0
NL80211_RRF_NO_IR |
- NL80211_RRF_NO_OFDM),
+ NL80211_RRF_NO_OFDM
+ #endif
+ 0),
/* IEEE 802.11a, channel 36..48 */
REG_RULE(5180-10, 5240+10, 80, 6, 20,
NL80211_RRF_NO_IR |
diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh
index 564db354..e05ecf76 100755
--- a/scripts/adjust_autoksyms.sh
+++ b/scripts/adjust_autoksyms.sh
@@ -51,6 +51,17 @@ esac
# In case it doesn't exist yet...
if [ -e "$cur_ksyms_file" ]; then touch "$cur_ksyms_file"; fi
+ksym_wl=/dev/null
+if [ -n "$CONFIG_UNUSED_KSYMS_WHITELIST" ]; then
+ # Use 'eval' to expand the whitelist path and check if it is relative
+ eval ksym_wl="$CONFIG_UNUSED_KSYMS_WHITELIST"
+ [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$srctree/$ksym_wl"
+ if [ ! -f "$ksym_wl" ]; then
+ echo "ERROR: '$ksym_wl' whitelist file not found" >&2
+ exit 1
+ fi
+fi
+
# Generate a new ksym list file with symbols needed by the current
# set of modules.
cat > "$new_ksyms_file" << EOT
@@ -59,7 +70,7 @@ cat > "$new_ksyms_file" << EOT
*/
EOT
-sed -ns -e '3{s/ /\n/g;/^$/!p;}' "$MODVERDIR"/*.mod | sort -u |
+sed -ns -e '3{s/ /\n/g;/^$/!p;}' "$MODVERDIR"/*.mod | cat - "$ksym_wl" | sort -u |
while read sym; do
if [ -n "$CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX" ]; then
sym="${sym#_}"
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 88b3dc19..1e4dea79 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1975,7 +1975,7 @@ static void read_symbols(char *modname)
if (version)
maybe_frob_rcs_version(modname, version, info.modinfo,
version - (char *)info.hdr);
- if (version || (all_versions && !is_vmlinux(modname)))
+ if ((all_versions && !is_vmlinux(modname)))
get_src_version(modname, mod->srcversion,
sizeof(mod->srcversion)-1);
diff --git a/tools/crypto/Makefile b/tools/crypto/Makefile
new file mode 100644
index 00000000..16b331a8
--- /dev/null
+++ b/tools/crypto/Makefile
@@ -0,0 +1,15 @@
+
+
+CC = $(CROSS_COMPILE)gcc
+#PTHREAD_LIBS = -lpthread
+#WARNINGS = -Wall -Wextra
+#CFLAGS = $(WARNINGS) -g -I../include
+#LDFLAGS = $(PTHREAD_LIBS)
+
+all: test_crypto
+%: %.c
+ $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+clean:
+ $(RM) test_crypto
+
diff --git a/tools/crypto/Readme.txt b/tools/crypto/Readme.txt
new file mode 100644
index 00000000..083e404b
--- /dev/null
+++ b/tools/crypto/Readme.txt
@@ -0,0 +1,9 @@
+该代码用来测试AES加密算法在各种工作模式ECB、CBC、CTR、CFB、OFB、各种密钥长度128、192、256下的加解密。
+最后通过比较解密结果和明文的内容来验证加解密是否正常。
+测试方法如下:
+1. 编译测试代码
+2. 将编译生成的可执行文件挂载到nfs目录下
+3. 开发板上电加载uImage进入kernel
+4. mount到nfs并进入nfs目录并执行
+
+ ./test_aes
\ No newline at end of file
diff --git a/tools/crypto/test_crypto.c b/tools/crypto/test_crypto.c
new file mode 100644
index 00000000..e98ff9be
--- /dev/null
+++ b/tools/crypto/test_crypto.c
@@ -0,0 +1,1059 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+#include <sys/socket.h>
+#include <linux/socket.h>
+#include <linux/if_alg.h>
+
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+struct crypt_cipher {
+ int tfmfd;
+ int opfd;
+};
+
+struct crypt_method {
+ char *type;
+ char *mode;
+ char *plain_buf;
+ char *encrypt_buf;
+ char *key_buf;
+ char *iv_buf;
+ int key_len;
+ int iv_len;
+ int text_len;
+};
+
+int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
+{
+ *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (*tfmfd == -1)
+ return -ENOTSUP;
+
+ if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) {
+ close(*tfmfd);
+ *tfmfd = -1;
+ return -ENOENT;
+ }
+
+ *opfd = accept(*tfmfd, NULL, 0);
+ if (*opfd == -1) {
+ close(*tfmfd);
+ *tfmfd = -1;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int crypt_cipher_destroy(struct crypt_cipher *ctx)
+{
+ if (ctx->tfmfd != -1)
+ close(ctx->tfmfd);
+ if (ctx->opfd != -1)
+ close(ctx->opfd);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+ return 0;
+}
+
+/*
+ *ciphers
+ *
+ * ENOENT - algorithm not available
+ * ENOTSUP - AF_ALG family not available
+ * (but cannot check specificaly for skcipher API)
+ */
+int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
+ const char *mode, const void *key_buf, size_t length)
+{
+ struct crypt_cipher *h;
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ };
+ int r;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
+ "%s(%s)", mode, name);
+
+ r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ if (length && strcmp(name, "cipher_null") &&
+ setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, key_buf, length) == -1) {
+ crypt_cipher_destroy(h);
+ return -EINVAL;
+ }
+
+ *ctx = h;
+ return 0;
+}
+
+/* The in/out should be aligned to page boundary */
+static int crypt_cipher_crypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ unsigned int direction)
+{
+ int r = 0;
+ ssize_t len;
+ struct af_alg_iv *alg_iv;
+ struct cmsghdr *header;
+ unsigned int *type;
+ struct iovec iov = {
+ .iov_base = (void*)(unsigned int *)in,
+ .iov_len = length,
+ };
+ int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
+ char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
+ struct msghdr msg = {
+ .msg_control = buffer,
+ .msg_controllen = sizeof(buffer),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ if (!in || !out || !length)
+ return -EINVAL;
+
+ if ((!iv && iv_length) || (iv && !iv_length))
+ return -EINVAL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Set encrypt/decrypt operation */
+ header = CMSG_FIRSTHDR(&msg);
+ if (!header)
+ return -EINVAL;
+
+ header->cmsg_level = SOL_ALG;
+ header->cmsg_type = ALG_SET_OP;
+ header->cmsg_len = CMSG_LEN(sizeof(*type));
+ type = (void*)CMSG_DATA(header);
+ *type = direction;
+
+ /* Set IV */
+ if (iv) {
+ header = CMSG_NXTHDR(&msg, header);
+ header->cmsg_level = SOL_ALG;
+ header->cmsg_type = ALG_SET_IV;
+ header->cmsg_len = iv_msg_size;
+ alg_iv = (void*)CMSG_DATA(header);
+ alg_iv->ivlen = iv_length;
+ memcpy(alg_iv->iv, iv, iv_length);
+ }
+
+ len = sendmsg(ctx->opfd, &msg, 0);
+ if (len != (ssize_t)length) {
+ r = -EIO;
+ goto bad;
+ }
+
+ len = read(ctx->opfd, out, length);
+ if (len != (ssize_t)length)
+ r = -EIO;
+bad:
+ return r;
+}
+
+int crypt_cipher_encrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_crypt(ctx, in, out, length,
+ iv, iv_length, ALG_OP_ENCRYPT);
+}
+
+int crypt_cipher_decrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_crypt(ctx, in, out, length,
+ iv, iv_length, ALG_OP_DECRYPT);
+}
+
+static const unsigned char plain_text[] = {
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+/* ================ aes cbc 128===================== */
+static const unsigned char aes_cbc_128_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_cbc_128_key_buf[] = {
+ 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
+};
+
+static const unsigned char aes_cbc_128_encrypt_text[] = {
+
+ 0x76,0x49,0xab,0xac, 0x81,0x19,0xb2,0x46, 0xce,0xe9,0x8e,0x9b, 0x12,0xe9,0x19,0x7d,
+ 0x50,0x86,0xcb,0x9b, 0x50,0x72,0x19,0xee, 0x95,0xdb,0x11,0x3a, 0x91,0x76,0x78,0xb2,
+ 0x73,0xbe,0xd6,0xb8, 0xe3,0xc1,0x74,0x3b, 0x71,0x16,0xe6,0x9e, 0x22,0x22,0x95,0x16,
+ 0x3f,0xf1,0xca,0xa1, 0x68,0x1f,0xac,0x09, 0x12,0x0e,0xca,0x30, 0x75,0x86,0xe1,0xa7,
+
+};
+
+/* ================ aes cbc 192===================== */
+static const unsigned char aes_cbc_192_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_cbc_192_key_buf[] = {
+ 0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
+ 0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
+};
+
+static const unsigned char aes_cbc_192_encrypt_text[] = {
+ 0x4f,0x02,0x1d,0xb2, 0x43,0xbc,0x63,0x3d, 0x71,0x78,0x18,0x3a, 0x9f,0xa0,0x71,0xe8,
+ 0xb4,0xd9,0xad,0xa9, 0xad,0x7d,0xed,0xf4, 0xe5,0xe7,0x38,0x76, 0x3f,0x69,0x14,0x5a,
+ 0x57,0x1b,0x24,0x20, 0x12,0xfb,0x7a,0xe0, 0x7f,0xa9,0xba,0xac, 0x3d,0xf1,0x02,0xe0,
+ 0x08,0xb0,0xe2,0x79, 0x88,0x59,0x88,0x81, 0xd9,0x20,0xa9,0xe6, 0x4f,0x56,0x15,0xcd,
+};
+
+/* ================ aes cbc 256===================== */
+static const unsigned char aes_cbc_256_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_cbc_256_key_buf[] = {
+ 0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
+ 0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
+};
+
+static const unsigned char aes_cbc_256_encrypt_text[] = {
+ 0xf5,0x8c,0x4c,0x04, 0xd6,0xe5,0xf1,0xba, 0x77,0x9e,0xab,0xfb, 0x5f,0x7b,0xfb,0xd6,
+ 0x9c,0xfc,0x4e,0x96, 0x7e,0xdb,0x80,0x8d, 0x67,0x9f,0x77,0x7b, 0xc6,0x70,0x2c,0x7d,
+ 0x39,0xf2,0x33,0x69, 0xa9,0xd9,0xba,0xcf, 0xa5,0x30,0xe2,0x63, 0x04,0x23,0x14,0x61,
+ 0xb2,0xeb,0x05,0xe2, 0xc3,0x9b,0xe9,0xfc, 0xda,0x6c,0x19,0x07, 0x8c,0x6a,0x9d,0x1b,
+};
+
+/* ================ aes ecb 128===================== */
+static const unsigned char aes_ecb_128_key_buf[] = {
+ 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
+};
+
+static const unsigned char aes_ecb_128_encrypt_text[] =
+{
+ 0x3a,0xd7,0x7b,0xb4, 0x0d,0x7a,0x36,0x60, 0xa8,0x9e,0xca,0xf3, 0x24,0x66,0xef,0x97,
+ 0xf5,0xd3,0xd5,0x85, 0x03,0xb9,0x69,0x9d, 0xe7,0x85,0x89,0x5a, 0x96,0xfd,0xba,0xaf,
+ 0x43,0xb1,0xcd,0x7f, 0x59,0x8e,0xce,0x23, 0x88,0x1b,0x00,0xe3, 0xed,0x03,0x06,0x88,
+ 0x7b,0x0c,0x78,0x5e, 0x27,0xe8,0xad,0x3f, 0x82,0x23,0x20,0x71, 0x04,0x72,0x5d,0xd4,
+};
+
+/* ================ aes ecb 192===================== */
+static const unsigned char aes_ecb_192_key_buf[] = {
+ 0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
+ 0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
+};
+
+static const unsigned char aes_ecb_192_encrypt_text[] =
+{
+ 0xbd,0x33,0x4f,0x1d, 0x6e,0x45,0xf2,0x5f, 0xf7,0x12,0xa2,0x14, 0x57,0x1f,0xa5,0xcc,
+ 0x97,0x41,0x04,0x84, 0x6d,0x0a,0xd3,0xad, 0x77,0x34,0xec,0xb3, 0xec,0xee,0x4e,0xef,
+ 0xef,0x7a,0xfd,0x22, 0x70,0xe2,0xe6,0x0a, 0xdc,0xe0,0xba,0x2f, 0xac,0xe6,0x44,0x4e,
+ 0x9a,0x4b,0x41,0xba, 0x73,0x8d,0x6c,0x72, 0xfb,0x16,0x69,0x16, 0x03,0xc1,0x8e,0x0e,
+};
+
+/* ================ aes ecb 256===================== */
+static const unsigned char aes_ecb_256_key_buf[] = {
+ 0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
+ 0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
+};
+
+static const unsigned char aes_ecb_256_encrypt_text[] =
+{
+ 0xf3,0xee,0xd1,0xbd, 0xb5,0xd2,0xa0,0x3c, 0x06,0x4b,0x5a,0x7e, 0x3d,0xb1,0x81,0xf8,
+ 0x59,0x1c,0xcb,0x10, 0xd4,0x10,0xed,0x26, 0xdc,0x5b,0xa7,0x4a, 0x31,0x36,0x28,0x70,
+ 0xb6,0xed,0x21,0xb9, 0x9c,0xa6,0xf4,0xf9, 0xf1,0x53,0xe7,0xb1, 0xbe,0xaf,0xed,0x1d,
+ 0x23,0x30,0x4b,0x7a, 0x39,0xf9,0xf3,0xff, 0x06,0x7d,0x8d,0x8f, 0x9e,0x24,0xec,0xc7,
+};
+
+/* ================ aes ctr 128===================== */
+static const unsigned char aes_ctr_128_iv_buf[] = {
+ 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
+};
+
+static const unsigned char aes_ctr_128_key_buf[] = {
+ 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
+};
+
+static const unsigned char aes_ctr_128_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char aes_ctr_128_encrypt_text[] =
+{
+ 0x87,0x4d,0x61,0x91, 0xb6,0x20,0xe3,0x26, 0x1b,0xef,0x68,0x64, 0x99,0x0d,0xb6,0xce,
+ 0x98,0x06,0xf6,0x6b, 0x79,0x70,0xfd,0xff, 0x86,0x17,0x18,0x7b, 0xb9,0xff,0xfd,0xff,
+ 0x5a,0xe4,0xdf,0x3e, 0xdb,0xd5,0xd3,0x5e, 0x5b,0x4f,0x09,0x02, 0x0d,0xb0,0x3e,0xab,
+ 0x1e,0x03,0x1d,0xda, 0x2f,0xbe,0x03,0xd1, 0x79,0x21,0x70,0xa0, 0xf3,0x00,0x9c,0xee,
+};
+
+/* ================ aes ctr 192===================== */
+static const unsigned char aes_ctr_192_iv_buf[] = {
+ 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
+};
+
+static const unsigned char aes_ctr_192_key_buf[] = {
+ 0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
+ 0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
+};
+
+static const unsigned char aes_ctr_192_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char aes_ctr_192_encrypt_text[] =
+{
+ 0x1a,0xbc,0x93,0x24, 0x17,0x52,0x1c,0xa2, 0x4f,0x2b,0x04,0x59, 0xfe,0x7e,0x6e,0x0b,
+ 0x09,0x03,0x39,0xec, 0x0a,0xa6,0xfa,0xef, 0xd5,0xcc,0xc2,0xc6, 0xf4,0xce,0x8e,0x94,
+ 0x1e,0x36,0xb2,0x6b, 0xd1,0xeb,0xc6,0x70, 0xd1,0xbd,0x1d,0x66, 0x56,0x20,0xab,0xf7,
+ 0x4f,0x78,0xa7,0xf6, 0xd2,0x98,0x09,0x58, 0x5a,0x97,0xda,0xec, 0x58,0xc6,0xb0,0x50,
+};
+
+/* ================ aes ctr 256===================== */
+static const unsigned char aes_ctr_256_iv_buf[] = {
+ 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
+};
+
+static const unsigned char aes_ctr_256_key_buf[] = {
+ 0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
+ 0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
+};
+
+static const unsigned char aes_ctr_256_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char aes_ctr_256_encrypt_text[] =
+{
+ 0x60,0x1e,0xc3,0x13, 0x77,0x57,0x89,0xa5, 0xb7,0xa7,0xf5,0x04, 0xbb,0xf3,0xd2,0x28,
+ 0xf4,0x43,0xe3,0xca, 0x4d,0x62,0xb5,0x9a, 0xca,0x84,0xe9,0x90, 0xca,0xca,0xf5,0xc5,
+ 0x2b,0x09,0x30,0xda, 0xa2,0x3d,0xe9,0x4c, 0xe8,0x70,0x17,0xba, 0x2d,0x84,0x98,0x8d,
+ 0xdf,0xc9,0xc5,0x8d, 0xb6,0x7a,0xad,0xa6, 0x13,0xc2,0xdd,0x08, 0x45,0x79,0x41,0xa6,
+};
+
+/* ================ aes ofb 128===================== */
+static const unsigned char aes_ofb_128_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_ofb_128_key_buf[] = {
+ 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
+};
+
+static const unsigned char aes_ofb_128_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char aes_ofb_128_encrypt_text[] =
+{
+ 0x3b,0x3f,0xd9,0x2e, 0xb7,0x2d,0xad,0x20, 0x33,0x34,0x49,0xf8, 0xe8,0x3c,0xfb,0x4a,
+ 0x77,0x89,0x50,0x8d, 0x16,0x91,0x8f,0x03, 0xf5,0x3c,0x52,0xda, 0xc5,0x4e,0xd8,0x25,
+ 0x97,0x40,0x05,0x1e, 0x9c,0x5f,0xec,0xf6, 0x43,0x44,0xf7,0xa8, 0x22,0x60,0xed,0xcc,
+ 0x30,0x4c,0x65,0x28, 0xf6,0x59,0xc7,0x78, 0x66,0xa5,0x10,0xd9, 0xc1,0xd6,0xae,0x5e,
+};
+
+/* ================ aes ofb 192===================== */
+static const unsigned char aes_ofb_192_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_ofb_192_key_buf[] = {
+ 0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
+ 0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
+};
+
+static const unsigned char aes_ofb_192_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char aes_ofb_192_encrypt_text[] =
+{
+ 0xcd,0xc8,0x0d,0x6f, 0xdd,0xf1,0x8c,0xab, 0x34,0xc2,0x59,0x09, 0xc9,0x9a,0x41,0x74,
+ 0xfc,0xc2,0x8b,0x8d, 0x4c,0x63,0x83,0x7c, 0x09,0xe8,0x17,0x00, 0xc1,0x10,0x04,0x01,
+ 0x8d,0x9a,0x9a,0xea, 0xc0,0xf6,0x59,0x6f, 0x55,0x9c,0x6d,0x4d, 0xaf,0x59,0xa5,0xf2,
+ 0x6d,0x9f,0x20,0x08, 0x57,0xca,0x6c,0x3e, 0x9c,0xac,0x52,0x4b, 0xd9,0xac,0xc9,0x2a,
+};
+
+/* ================ aes ofb 256===================== */
+static const unsigned char aes_ofb_256_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_ofb_256_key_buf[] = {
+ 0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
+ 0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
+};
+
+static const unsigned char aes_ofb_256_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+ 0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c, 0x9e,0xb7,0x6f,0xac, 0x45,0xaf,0x8e,0x51,
+ 0x30,0xc8,0x1c,0x46, 0xa3,0x5c,0xe4,0x11, 0xe5,0xfb,0xc1,0x19, 0x1a,0x0a,0x52,0xef,
+ 0xf6,0x9f,0x24,0x45, 0xdf,0x4f,0x9b,0x17, 0xad,0x2b,0x41,0x7b, 0xe6,0x6c,0x37,0x10,
+};
+
+static const unsigned char aes_ofb_256_encrypt_text[] =
+{
+ 0xdc,0x7e,0x84,0xbf, 0xda,0x79,0x16,0x4b, 0x7e,0xcd,0x84,0x86, 0x98,0x5d,0x38,0x60,
+ 0x4f,0xeb,0xdc,0x67, 0x40,0xd2,0x0b,0x3a, 0xc8,0x8f,0x6a,0xd8, 0x2a,0x4f,0xb0,0x8d,
+ 0x71,0xab,0x47,0xa0, 0x86,0xe8,0x6e,0xed, 0xf3,0x9d,0x1c,0x5b, 0xba,0x97,0xc4,0x08,
+ 0x01,0x26,0x14,0x1d, 0x67,0xf3,0x7b,0xe8, 0x53,0x8f,0x5a,0x8b, 0xe7,0x40,0xe4,0x84,
+};
+
+/* ================ aes cfb 128===================== */
+static const unsigned char aes_cfb_128_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_cfb_128_key_buf[] = {
+ 0x2b,0x7e,0x15,0x16, 0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88, 0x09,0xcf,0x4f,0x3c,
+};
+
+static const unsigned char aes_cfb_128_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+};
+
+static const unsigned char aes_cfb_128_encrypt_text[] =
+{
+ 0x3b,0x79,0x42,0x4c, 0x9c,0x0d,0xd4,0x36, 0xba,0xce,0x9e,0x0e, 0xd4,0x58,0x6a,0x4f,
+};
+
+/* ================ aes cfb 192===================== */
+static const unsigned char aes_cfb_192_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_cfb_192_key_buf[] = {
+ 0x8e,0x73,0xb0,0xf7, 0xda,0x0e,0x64,0x52, 0xc8,0x10,0xf3,0x2b, 0x80,0x90,0x79,0xe5,
+ 0x62,0xf8,0xea,0xd2, 0x52,0x2c,0x6b,0x7b,
+};
+
+static const unsigned char aes_cfb_192_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+};
+
+static const unsigned char aes_cfb_192_encrypt_text[] =
+{
+ 0xcd,0xa2,0x52,0x1e, 0xf0,0xa9,0x05,0xca, 0x44,0xcd,0x05,0x7c, 0xbf,0x0d,0x47,0xa0,
+};
+
+/* ================ aes cfb 256===================== */
+static const unsigned char aes_cfb_256_iv_buf[] = {
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+};
+
+static const unsigned char aes_cfb_256_key_buf[] = {
+ 0x60,0x3d,0xeb,0x10, 0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0, 0x85,0x7d,0x77,0x81,
+ 0x1f,0x35,0x2c,0x07, 0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3, 0x09,0x14,0xdf,0xf4,
+};
+
+static const unsigned char aes_cfb_256_plain_text[] =
+{
+ 0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
+};
+
+static const unsigned char aes_cfb_256_encrypt_text[] =
+{
+ 0xdc,0x1f,0x1a,0x85, 0x20,0xa6,0x4d,0xb5, 0x5f,0xcc,0x8a,0xc5, 0x54,0x84,0x4e,0x88,
+};
+
+/* ================ des ecb ===================== */
+static const unsigned char des_ecb_key_buf[] = {
+ 0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,
+};
+
+static const unsigned char des_ecb_plain_text[] =
+{
+ 0x80,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x40,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x10,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x08,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x04,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
+};
+
+static const unsigned char des_ecb_encrypt_text[] =
+{
+ 0x95,0xF8,0xA5,0xE5, 0xDD,0x31,0xD9,0x00, 0xDD,0x7F,0x12,0x1C, 0xA5,0x01,0x56,0x19,
+ 0x2E,0x86,0x53,0x10, 0x4F,0x38,0x34,0xEA, 0x4B,0xD3,0x88,0xFF, 0x6C,0xD8,0x1D,0x4F,
+ 0x20,0xB9,0xE7,0x67, 0xB2,0xFB,0x14,0x56, 0x55,0x57,0x93,0x80, 0xD7,0x71,0x38,0xEF,
+ 0x6C,0xC5,0xDE,0xFA, 0xAF,0x04,0x51,0x2F, 0x0D,0x9F,0x27,0x9B, 0xA5,0xD8,0x72,0x60,
+};
+
+/* ================ des cbc ===================== */
+static const unsigned char des_cbc_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_cbc_iv_buf[] = {
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_cbc_plain_text[] =
+{
+ 0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x68,0x65,0x20,0x74, 0x69,0x6d,0x65,0x20,
+ 0x66,0x6f,0x72,0x20, 0x61,0x6c,0x6c,0x20,
+
+};
+
+static const unsigned char des_cbc_encrypt_text[] =
+{
+ 0xe5,0xc7,0xcd,0xde, 0x87,0x2b,0xf2,0x7c, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
+};
+
+/* ================ des ofb ===================== */
+static const unsigned char des_ofb_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_ofb_iv_buf[] = {
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_ofb_plain_text[] =
+{
+ 0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char des_ofb_encrypt_text[] =
+{
+ 0xf3,0x09,0x62,0x49, 0xc7,0xf4,0x6e,0x51, 0x1e,0x7e,0x5e,0x50, 0xcb,0xbe,0xc4,0x10,
+ 0x33,0x35,0xa1,0x8a, 0xde,0x4a,0x91,0x15,
+};
+
+/* ================ des cfb ===================== */
+static const unsigned char des_cfb_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_cfb_iv_buf[] = {
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+
+static const unsigned char des_cfb_plain_text[] =
+{
+ 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char des_cfb_encrypt_text[] =
+{
+ 0xf3,0x1f,0xda,0x07,0x01,0x14,0x62,0xee,0x33,0x79,0xda,0x67,0xd6,0xd8,0x94,0x3b,
+ 0x71,0xde,0xe2,0xf3,0x50,0x80,0xd6,0x2b,
+};
+
+/* ================ des3 ecb ===================== */
+static const unsigned char des3_ecb_key_buf[] = {
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
+ 0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
+};
+
+static const unsigned char des3_ecb_plain_text[] =
+{
+ 0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char des3_ecb_encrypt_text[] =
+{
+ 0x31,0x4f,0x83,0x27, 0xfa,0x7a,0x09,0xa8, 0xd5,0x89,0x5f,0xad, 0xe9,0x8f,0xae,0xdf,
+ 0x98,0xf4,0x70,0xeb, 0x35,0x53,0xa5,0xda,
+};
+
+/* ================ des3 cbc ===================== */
+static const unsigned char des3_cbc_key_buf[] =
+{
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
+ 0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
+};
+
+static const unsigned char des3_cbc_iv_buf[] =
+{
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+
+static const unsigned char des3_cbc_plain_text[] =
+{
+ 0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char des3_cbc_encrypt_text[] =
+{
+ 0xf3,0xc0,0xff,0x02, 0x6c,0x02,0x30,0x89, 0xc4,0x3a,0xdd,0x8f, 0xd8,0xcd,0x5e,0x43,
+ 0x2b,0xfd,0x41,0xd3, 0x13,0x0b,0xcf,0x40,
+};
+
+/* ================ des3 ofb ===================== */
+static const unsigned char des3_ofb_key_buf[] =
+{
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
+ 0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
+};
+
+static const unsigned char des3_ofb_iv_buf[] =
+{
+ 0x23,0x45,0x67,0x89 ,0x0a,0xbc,0xde,0x0f,
+};
+
+static const unsigned char des3_ofb_plain_text[] =
+{
+ 0xe6,0xf7,0x72,0x06, 0x97,0x32,0x07,0x04, 0x3e,0x93,0x40,0x08, 0xc3,0x89,0xc0,0x0f,
+ 0x83,0x78,0x84,0x99, 0xa7,0xc0,0x5f,0x06,
+};
+
+static const unsigned char des3_ofb_encrypt_text[] =
+{
+ 0xf3,0x24,0x21,0x7f, 0xf3,0x55,0x3c,0x3b, 0xe7,0x46,0x2d,0x4a, 0xe5,0xed,0x98,0x27,
+ 0x05,0x17,0x55,0x81, 0xf8,0x62,0x5b,0xa6,
+};
+
+/* ================ des3 cfb ===================== */
+static const unsigned char des3_cfb_key_buf[] =
+{
+ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0x23,0x45,0x67,0x89, 0xab,0xcd,0xef,0x01,
+ 0x45,0x67,0x89,0xab, 0xcd,0xef,0x01,0x23,
+};
+
+static const unsigned char des3_cfb_iv_buf[] =
+{
+ 0x12,0x34,0x56,0x78, 0x90,0xab,0xcd,0xef,
+};
+
+static const unsigned char des3_cfb_plain_text[] =
+{
+ 0x4e,0x6f,0x77,0x20, 0x69,0x73,0x20,0x74, 0x43,0xe9,0x34,0x00, 0x8c,0x38,0x9c,0x0f,
+ 0x68,0x37,0x88,0x49, 0x9a,0x7c,0x05,0xf6,
+};
+
+static const unsigned char des3_cfb_encrypt_text[] =
+{
+ 0xee,0x9b,0x04,0xff, 0xca,0xce,0xc8,0x06, 0x5b,0xcc,0x4f,0x67, 0x8f,0x00,0xd7,0x14,
+ 0x4d,0xf6,0x74,0xfc, 0xd6,0x98,0x9f,0x8f,
+};
+
+int runtest(struct crypt_method *method)
+{
+ struct crypt_cipher *cipher;
+ unsigned char *in, *out, *tmp;
+ long page_size;
+
+ /*just for dubug..printf the result of encrypt*/
+ /*
+ int i = 0;
+ unsigned char result[64];
+ int *p = result;
+ */
+ /*end*/
+
+ int ret = 0;
+
+ page_size = sysconf(_SC_PAGESIZE);
+ tmp = malloc(method->text_len + page_size);
+ if (tmp == NULL) {
+ printf("error: malloc buffer failed.\n");
+ return -1;
+ }
+ in = (unsigned char *)( ((long)tmp + page_size - 1) & ~(page_size - 1) );
+
+ tmp = malloc(method->text_len + page_size);
+ if (tmp == NULL) {
+ printf("error: malloc buffer failed.\n");
+ return -1;
+ }
+ out = (unsigned char *)( ((long)tmp + page_size - 1) & ~(page_size - 1) );
+
+ ret = crypt_cipher_init(&cipher, method->type, method->mode, method->key_buf, method->key_len);
+ if (0 != ret) {
+ printf("error: crypt_cipher_init failed, ret=%d\n", ret);
+ return ret;
+ }
+
+ memcpy(in, method->plain_buf, method->text_len);
+ memset(out, 0, method->text_len);
+ ret = crypt_cipher_encrypt(cipher, (const char *)in, (char *)out, method->text_len, (const char *)method->iv_buf, method->iv_len);
+ if (0 != ret) {
+ printf("error: crypt_cipher_encrypt failed, ret=%d\n", ret);
+ goto exit;
+ }
+
+ /*debug...printf the result of encrypt*/
+ /*
+ memcpy(p, out, method->text_len);
+ for (i = 0; i < 24; i++) {
+ printf("times: %d, Ciphertest: %x\n", i, result[i]);
+ printf("\n");
+ }
+ */
+
+ ///*
+ if (0 != memcmp(method->encrypt_buf, out, method->text_len))
+ printf("FAIL -> %s(%s) Encrypt test\n", method->mode, method->type);
+ else
+ printf("PASS -> %s(%s) Encrypt test\n", method->mode, method->type);
+
+ memcpy(in, method->encrypt_buf, method->text_len);
+ memset(out, 0, method->text_len);
+ ret = crypt_cipher_decrypt(cipher, (const char *)in, (char *)out, method->text_len, (const char *)method->iv_buf, method->iv_len);
+ if (0 != ret) {
+ printf("error: crypt_cipher_decrypt failed, ret=%d\n", ret);
+ goto exit;
+ }
+ if (0 != memcmp((unsigned char*)method->plain_buf, out, method->text_len))
+ printf("FAIL -> %s(%s) Decrypt test\n", method->mode, method->type);
+ else
+ printf("PASS -> %s(%s) Decrypt test\n", method->mode, method->type);
+ //*/
+exit:
+ crypt_cipher_destroy(cipher);
+ return ret;
+}
+
+int main(int argc, char const *argv[])
+{
+ struct crypt_method aes_cbc_128 = {
+ .type = "aes",
+ .mode = "cbc",
+ .plain_buf = (char *)plain_text,
+ .encrypt_buf = (char *)aes_cbc_128_encrypt_text,
+ .key_buf = (char *)aes_cbc_128_key_buf,
+ .key_len = 16,
+ .iv_buf = (char *)aes_cbc_128_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_cbc_192 = {
+ .type = "aes",
+ .mode = "cbc",
+ .plain_buf = (char *)plain_text,
+ .encrypt_buf = (char *)aes_cbc_192_encrypt_text,
+ .key_buf = (char *)aes_cbc_192_key_buf,
+ .key_len = 24,
+ .iv_buf = (char *)aes_cbc_192_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_cbc_256 = {
+ .type = "aes",
+ .mode = "cbc",
+ .plain_buf = (char *)plain_text,
+ .encrypt_buf = (char *)aes_cbc_256_encrypt_text,
+ .key_buf = (char *)aes_cbc_256_key_buf,
+ .key_len = 32,
+ .iv_buf = (char *)aes_cbc_256_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ecb_128 = {
+ .type = "aes",
+ .mode = "ecb",
+ .plain_buf = (char *)plain_text,
+ .encrypt_buf = (char *)aes_ecb_128_encrypt_text,
+ .key_buf = (char *)aes_ecb_128_key_buf,
+ .key_len = 16,
+ .iv_buf = NULL,
+ .iv_len = 0,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ecb_192 = {
+ .type = "aes",
+ .mode = "ecb",
+ .plain_buf = (char *)plain_text,
+ .encrypt_buf = (char *)aes_ecb_192_encrypt_text,
+ .key_buf = (char *)aes_ecb_192_key_buf,
+ .key_len = 24,
+ .iv_buf = NULL,
+ .iv_len = 0,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ecb_256 = {
+ .type = "aes",
+ .mode = "ecb",
+ .plain_buf = (char *)plain_text,
+ .encrypt_buf = (char *)aes_ecb_256_encrypt_text,
+ .key_buf = (char *)aes_ecb_256_key_buf,
+ .key_len = 32,
+ .iv_buf = NULL,
+ .iv_len = 0,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ctr_128 = {
+ .type = "aes",
+ .mode = "ctr",
+ .plain_buf = (char *)aes_ctr_128_plain_text,
+ .encrypt_buf = (char *)aes_ctr_128_encrypt_text,
+ .key_buf = (char *)aes_ctr_128_key_buf,
+ .key_len = 16,
+ .iv_buf = (char *)aes_ctr_128_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ctr_192 = {
+ .type = "aes",
+ .mode = "ctr",
+ .plain_buf = (char *)aes_ctr_192_plain_text,
+ .encrypt_buf = (char *)aes_ctr_192_encrypt_text,
+ .key_buf = (char *)aes_ctr_192_key_buf,
+ .key_len = 24,
+ .iv_buf = (char *)aes_ctr_192_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ctr_256 = {
+ .type = "aes",
+ .mode = "ctr",
+ .plain_buf = (char *)aes_ctr_256_plain_text,
+ .encrypt_buf = (char *)aes_ctr_256_encrypt_text,
+ .key_buf = (char *)aes_ctr_256_key_buf,
+ .key_len = 32,
+ .iv_buf = (char *)aes_ctr_256_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ofb_128 = {
+ .type = "aes",
+ .mode = "ofb",
+ .plain_buf = (char *)aes_ofb_128_plain_text,
+ .encrypt_buf = (char *)aes_ofb_128_encrypt_text,
+ .key_buf = (char *)aes_ofb_128_key_buf,
+ .key_len = 16,
+ .iv_buf = (char *)aes_ofb_128_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ofb_192 = {
+ .type = "aes",
+ .mode = "ofb",
+ .plain_buf = (char *)aes_ofb_192_plain_text,
+ .encrypt_buf = (char *)aes_ofb_192_encrypt_text,
+ .key_buf = (char *)aes_ofb_192_key_buf,
+ .key_len = 24,
+ .iv_buf = (char *)aes_ofb_192_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_ofb_256 = {
+ .type = "aes",
+ .mode = "ofb",
+ .plain_buf = (char *)aes_ofb_256_plain_text,
+ .encrypt_buf = (char *)aes_ofb_256_encrypt_text,
+ .key_buf = (char *)aes_ofb_256_key_buf,
+ .key_len = 32,
+ .iv_buf = (char *)aes_ofb_256_iv_buf,
+ .iv_len = 16,
+ .text_len = 64
+ };
+
+ struct crypt_method aes_cfb_128 = {
+ .type = "aes",
+ .mode = "cfb",
+ .plain_buf = (char *)aes_cfb_128_plain_text,
+ .encrypt_buf = (char *)aes_cfb_128_encrypt_text,
+ .key_buf = (char *)aes_cfb_128_key_buf,
+ .key_len = 16,
+ .iv_buf = (char *)aes_cfb_128_iv_buf,
+ .iv_len = 16,
+ .text_len = 16
+ };
+
+ struct crypt_method aes_cfb_192 = {
+ .type = "aes",
+ .mode = "cfb",
+ .plain_buf = (char *)aes_cfb_192_plain_text,
+ .encrypt_buf = (char *)aes_cfb_192_encrypt_text,
+ .key_buf = (char *)aes_cfb_192_key_buf,
+ .key_len = 24,
+ .iv_buf = (char *)aes_cfb_192_iv_buf,
+ .iv_len = 16,
+ .text_len = 16
+ };
+
+ struct crypt_method aes_cfb_256 = {
+ .type = "aes",
+ .mode = "cfb",
+ .plain_buf = (char *)aes_cfb_256_plain_text,
+ .encrypt_buf = (char *)aes_cfb_256_encrypt_text,
+ .key_buf = (char *)aes_cfb_256_key_buf,
+ .key_len = 32,
+ .iv_buf = (char *)aes_cfb_256_iv_buf,
+ .iv_len = 16,
+ .text_len = 16
+ };
+
+ struct crypt_method des_ecb = {
+ .type = "des",
+ .mode = "ecb",
+ .plain_buf = (char *)des_ecb_plain_text,
+ .encrypt_buf = (char *)des_ecb_encrypt_text,
+ .key_buf = (char *)des_ecb_key_buf,
+ .key_len = 8,
+ .iv_buf = NULL,
+ .iv_len = 0,
+ .text_len = 64
+ };
+
+ struct crypt_method des_cbc = {
+ .type = "des",
+ .mode = "cbc",
+ .plain_buf = (char *)des_cbc_plain_text,
+ .encrypt_buf = (char *)des_cbc_encrypt_text,
+ .key_buf = (char *)des_cbc_key_buf,
+ .key_len = 8,
+ .iv_buf = (char *)des_cbc_iv_buf,
+ .iv_len = 8,
+ .text_len = 24
+ };
+
+ struct crypt_method des_ofb = {
+ .type = "des",
+ .mode = "ofb",
+ .plain_buf = (char *)des_ofb_plain_text,
+ .encrypt_buf = (char *)des_ofb_encrypt_text,
+ .key_buf = (char *)des_ofb_key_buf,
+ .key_len = 8,
+ .iv_buf = (char *)des_ofb_iv_buf,
+ .iv_len = 8,
+ .text_len = 24
+ };
+
+ struct crypt_method des_cfb = {
+ .type = "des",
+ .mode = "cfb",
+ .plain_buf = (char *)des_cfb_plain_text,
+ .encrypt_buf = (char *)des_cfb_encrypt_text,
+ .key_buf = (char *)des_cfb_key_buf,
+ .key_len = 8,
+ .iv_buf = (char *)des_cfb_iv_buf,
+ .iv_len = 8,
+ .text_len = 24
+ };
+
+ struct crypt_method des3_ecb = {
+ .type = "des3",
+ .mode = "ecb",
+ .plain_buf = (char *)des3_ecb_plain_text,
+ .encrypt_buf = (char *)des3_ecb_encrypt_text,
+ .key_buf = (char *)des3_ecb_key_buf,
+ .key_len = 24,
+ .iv_buf = NULL,
+ .iv_len = 0,
+ .text_len = 24
+ };
+
+ struct crypt_method des3_cbc = {
+ .type = "des3",
+ .mode = "cbc",
+ .plain_buf = (char *)des3_cbc_plain_text,
+ .encrypt_buf = (char *)des3_cbc_encrypt_text,
+ .key_buf = (char *)des3_cbc_key_buf,
+ .key_len = 24,
+ .iv_buf = (char *)des3_cbc_iv_buf,
+ .iv_len = 8,
+ .text_len = 24
+ };
+
+ struct crypt_method des3_ofb = {
+ .type = "des3",
+ .mode = "ofb",
+ .plain_buf = (char *)des3_ofb_plain_text,
+ .encrypt_buf = (char *)des3_ofb_encrypt_text,
+ .key_buf = (char *)des3_ofb_key_buf,
+ .key_len = 24,
+ .iv_buf = (char *)des3_ofb_iv_buf,
+ .iv_len = 8,
+ .text_len = 24
+ };
+
+ struct crypt_method des3_cfb = {
+ .type = "des3",
+ .mode = "cfb",
+ .plain_buf = (char *)des3_cfb_plain_text,
+ .encrypt_buf = (char *)des3_cfb_encrypt_text,
+ .key_buf = (char *)des3_cfb_key_buf,
+ .key_len = 24,
+ .iv_buf = (char *)des3_cfb_iv_buf,
+ .iv_len = 8,
+ .text_len = 24
+ };
+
+ runtest(&aes_cbc_128);
+ runtest(&aes_cbc_192);
+ runtest(&aes_cbc_256);
+ runtest(&aes_ecb_128);
+ runtest(&aes_ecb_192);
+ runtest(&aes_ecb_256);
+ runtest(&aes_ctr_128);
+ runtest(&aes_ctr_192);
+ runtest(&aes_ctr_256);
+ runtest(&aes_ofb_128);
+ runtest(&aes_ofb_192);
+ runtest(&aes_ofb_256);
+ runtest(&aes_cfb_128);
+ runtest(&aes_cfb_192);
+ runtest(&aes_cfb_256);
+ runtest(&des_ecb);
+ runtest(&des_cbc);
+ runtest(&des_ofb);
+ runtest(&des_cfb);
+ runtest(&des3_ecb);
+ runtest(&des3_cbc);
+ runtest(&des3_ofb);
+ runtest(&des3_cfb);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/usr/Makefile b/usr/Makefile
index e767f019..6f15f442 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -5,7 +5,7 @@
klibcdirs:;
PHONY += klibcdirs
-
+ifeq ($(CONFIG_EMULATION),)
# Bzip2
suffix_$(CONFIG_RD_BZIP2) = .bz2
@@ -23,6 +23,20 @@ suffix_$(CONFIG_RD_LZ4) = .lz4
# Gzip
suffix_$(CONFIG_RD_GZIP) = .gz
+else
+# force use rootfs.cpio, decompress rootfs.cpio.* to rootfs.cpio
+suffix := $(suffix $(CONFIG_INITRAMFS_SOURCE))
+ifeq ($(suffix), .xz")
+dec_cmd := unxz
+endif
+ifeq ($(suffix), .gz")
+dec_cmd := gunzip
+endif
+ifneq ($(dec_cmd),)
+$(shell $(dec_cmd) -kf $(CONFIG_INITRAMFS_SOURCE))
+export CONFIG_INITRAMFS_SOURCE := $(subst $(suffix),",$(CONFIG_INITRAMFS_SOURCE))
+endif
+endif
AFLAGS_initramfs_data.o += -DINITRAMFS_IMAGE="usr/initramfs_data.cpio$(suffix_y)"